The Demon Of Portability

Posted 20 Dec 2000 at 21:42 UTC by mrorganic Share This

There's an interesting debate here about the relative merits/drawbacks of writing UI-independant code for the LyX project. As such debates often do, the issue degenerated into advocacy camps: some like widget-agnostic code, some don't; some like formal OO methodologies (Model/View/Controller), some don't.

Ultimately, the question was not resolved so much as dropped. Were this issue limited to the LyX project it would only be of passing interest, but this exact problem devils many emerging GUI applications in the Linux space because of the many toolkits in use. The two most popular are GTK+/GNOME and QT/KDE, but there are others -- Motif is still popular, FLTK has its fans, and XForms is still around. Mozilla has introduced yet another variable with its XUL interface, allowing programmers to use the browser as a platform for GUI code.

Many developers (including myself) view this situation with a very jaundiced eye. Application developers often shy away from Linux (and other *nixes) because they cannot depend on a standard system API being present (like WIN32 or the Mac toolbox). And Users tend to be very vocal about their GUI of choice -- they tend to get soggy and hard to light if the application does not integrate well into the GUI. So if I as a developer choose GTK+ as the basis for my application, I am sure to get flamed by at least 50% of the user community for not using QT. Worse yet, interoperation with other applications is sure to be painful because GNOME folks use CORBA while KDE folks use DCOP, which are (naturally) incompatible. And I'm not even getting into the difficulties of providing services under different window-managers (which often interpret right-clicks and middle-clicks differently, or treat focus in a strange way).

One approach many have tried is to try and write GUI-independant code -- that is, code which abstracts the functional underpinnings away from the GUI "frosting". Mozilla actually reinvented the entire GUI itself (XUL). The success of these various projects is decidedly mixed -- they tend towards "lowest common denominator" feature-sets, and stability often suffers due to the complexity of the code.

The problem here I think is one of background: Unix developers are constitutionally incapable of consensus. It doesn't surprise me that there was no consensus on a common GUI API -- over the thirty years Unix has been around, there was no consensus on something as fundamental as a filesystem or C library! (Or thread library, or driver model, or initialization method, or ABI, or printing API, or.... But I digress.) As a longtime Unix hacker, I've always considered portability to be a Good Thing, but lately I've begun to wonder if that's really true. Theory tells me that writing portable code should lead to better code, but experience has shown decisively otherwise: native apps are easier to write, maintain, and extend. They are also, not coincidentally, more stable.

In the Linux world at least, the boat has sailed. There is no way to mandate a common GUI API at this late stage of the game (even assuming that a common API could be agreed upon). We must continue writing applications that sometimes work and sometimes don't, that can't communicate efficiently with each other, and that have to re-invent the wheel over and over again.

As a developer I can only wonder why we inflict this kind of pain on ourselves.


It's not that big a deal., posted 20 Dec 2000 at 22:45 UTC by egnor » (Journeyer)

Who's inflicting what on whom? What would you suggest as the alternative?

As a user, I will not "flame" you because you chose Gtk instead of Qt or vice versa. The beauty of X is that all these widget sets can run side by side. If your application is useful to me, I'll run it, even if you invent your own widget library. I'm sure there are some users out there for whom tight coupling to their desktop of choice (GNOME, KDE, or whatever) is important, and who care about having a common theme and Bonobo component embedding between all their apps, but it's definitely an exaggeration to say that 50% of your user base will complain because you chose the "wrong" widget set. Don't let the vocal minority sway your impression of the world.

So, what's your point, exactly? Would you take away freedom of choice and force KDE developers to work on GNOME instead (or vice versa)? (Who gets to decide which one wins?) Would you have us drop this whole "free operating system" nightmare and go to work writing Windows software, since Windows is clearly better because it doesn't offer all these confusing choices?

Now, the developers of competing platforms could work to enable interoperability. This is difficult because part of the reason they're in competition in the first place is that they have fundamentally different models of how software should be built. Nevertheless, there is some work going on to make sure that basic operations remain compatible. You're always free to lend your support to those efforts, of course.

Choice is part and parcel of freedom. Without choice, freedom is an illusion ("you can have any color you want, as long as it's black"). If we want free software, we must embrace the fact that we will be faced with choices. Over time, if the burden of choice exceeds the benefits of diversity, the community will pick something and move on (leaving only a few screaming zealots behind...). Perhaps this will happen to free GUI desktop environments in the future, but this isn't a process that will happen because you want it to (nor should it).

Meanwhile, you're left with the free person's burden: you must choose among the available alternatives, weighing the respective benefits of a framework you like, features you enjoy, and a user base who will prefer your product.

Freedom is about diversity, posted 20 Dec 2000 at 23:31 UTC by jao » (Journeyer)

I totally agree with egnor. Having different choices (of GUI toolkits or whatever) is a good thing: freedom implies choice; if you don't like GTK+ you can shift to Qt, or create your own solution: in the propietary software world, they don't give you such a chance.

On the other hand, if we left aside philosophycal considerations and focus on programming practice, I think that abstracting away the presentation layer of an application is the right thing to do, even if you don't plan to provide multiple interfaces to your application. The design is cleaner and far more elegant this way and, in my experience, the maintainability of the code increases. Using this approach in my own projects, i've been able, for instance, to provide CLI, curses and GTK+ front-ends to the same core functionality, maximising the reuse of code. Just my 2 cents...

And I agree..., posted 21 Dec 2000 at 01:08 UTC by DrCode » (Journeyer)

... with jao's agreement with egnor. Encapsulating the GUI interface is a good thing.

But, when you finally decide on a toolkit, my suggestion, as a long-time KDE user and C++ coder, is to use GTK. It's already ported to X and Win32. And although it's in C, I've found it very easy to use in C++ code: Represent a GUI component with a class; pass an instance as the 'data' to signal handlers; and use static methods as the signal handlers (so they have access to the instance's data). Plus, it's completely free, both in the 'free beer' and 'free speech' sense, with very readable source code. If you need it on another platform, like Mac or BeOS, it shouldn't be an impossible project to port GTK.

I'm sure QT is an excellent toolkit, probably even easier to use, judging by the quality of KDE 2. But I believe there are licensing costs if you want to use it with Win32.

portable GUI toolkits, posted 21 Dec 2000 at 01:56 UTC by atai » (Journeyer)

There are more (too many?) portable GUI toolkits than mentioned here. See

http://www.atai.org/guitool/

for a complete list, showing the supported platforms.

Quiet a few may be sufficient for the GUI of a word processor or document processor, if you are willing to avoid using nifty features unique to a platform.

Ah the pains of portability, posted 21 Dec 2000 at 03:09 UTC by jgg » (Master)

I think you are right. 'Portable', apps are hard to write, hard to maintain, and do nothing to improve the quality of the code. They often reduce it in fact! This is because most people take the #ifdef approach to portability which naturaly leads to ugly code.

The 'theory' that portable apps (system wise) are better stems from the implicit assumption that the path to portability is through removing non-standard problem areas and focusing on well understood standard APIs. It should be immediately clear that adding long conditional code paths immediately jacks up the complexity and kills testability.

IMHO portability among widget set (code that is widget set agnostic) should be reserved for applications that desperately need to do that for some reason (and even then, Java is a legitimate response) - the alternative is often alot of effort expended, and worthwhile shortcuts and features are ignored because they are not portable. In this case, building a reliable non-GUI core component. is often very hard, - and efficiently interfacing them is also tricky. Choosing to focus on the right components to be non-GUI will speed development and result in fewer layers of abstraction (ie simpler more robust code).

As far as widget sets go, IMHO the two major ones should work really hard to be largely seemless as far as the user goes - I hope the effort of building seperate implementations will result in APIs that better reflect their language segments rather than something like the hack that is MFC/OWL.

For System APIs the answer is clear - say NO to non-SUS and non-C99 environments. Write code that conforms to those APIs and punish those systems without by creating a compatibility layer if necessary. That is the only way we as developers can force these standards to be adopted quickly.

Don't write portable GUIs, posted 21 Dec 2000 at 03:57 UTC by Dacta » (Journeyer)

Concentrate on writing a stable and useful base system, with a refined API.

Encourage users/programmers to write GUIs in the toolkit of their choice.

This seems to have worked fairly well for things like MP3 players and CD-burner software. It would be a lot more difficult for something like a wordprocesser, though.

Why Strive for Consensus?, posted 21 Dec 2000 at 07:31 UTC by bagder » (Master)

    mrorganic wrote: The problem here I think is one of background: Unix developers are constitutionally incapable of consensus. It doesn't surprise me that there was no consensus on a common GUI API -- over the thirty years Unix has been around, there was no consensus on something as fundamental as a filesystem or C library!

  • Claiming that this is a unix problem is to hide from reality. This kind of problem exist everywhere where people have the means to say and decide what they want (like countries with democracy). Of course the windows world don't have this problem, as the dark side decides for everyone what to do. In a similar manner, a dictator may rule a country much better than a democracy due to "consensus" being achieved.

  • Consensus prevents development. Given that you mock every sheep into one single way of thinking and designing, you won't get as much inventions and new ways of doing things. Yes you get similarly behaving programs, but the dark side has proven this point as well if I was to tell.

  • As you say, this is inflicted on ourselves. We choose to do this, this is not something someone else have done to us. "You're all different" (Life of Brian - Monty Python). Very often, having a multitude of options better suits a large crowd since different people have different needs, philosophies and needs. That's why we stay away from the dark side, in the light sunshine of options.
  • Portability Is Not Applicable To Everything, posted 21 Dec 2000 at 10:41 UTC by nymia » (Master)

    One of the things that I've observed about it is that portability does and with 100% accuracy, always favor languages rather than environments, toolkits & libraries. Take for example: C, C++, Bash, Sed, AWK, Perl and other languages. They seem to have one thing in common in terms of portability and that is they can easily be ported to other platforms. One good reason why languages have this advantage is because of this simple thing: they're basically symbol processors. They operate on the lowest common denominator. Moreover, they play nicely with tokens and grammars which is basically found on all platforms.

    I for one is an advocate of pushing the envelope of a language, or even the creation of new languages, rather than adding feature upon feature on top of existing environments, toolkits and libraries simply because languages are much better to handle. On the other hand, environments and toolkits like <insert name here> will surely take the path of greater resistance when portability becomes a requirement. Plus, environments, toolkits and libraries depend on the operating system services which make it even harder for programmers to port.

    Bottomline here is that you have a good point about toolkit portability as they tend to be effective only on a subset of platforms.

    OO seems to help., posted 21 Dec 2000 at 14:59 UTC by dirtyrat » (Journeyer)

    I'm busy rewriting rCalc in C++, and I've found that the OO way of designing programs goes a long way to help you make applications portable.

    rCalc is a calculator, and the program is split into a GUI and a calculation engine. The GUI calls the calculation engine all the time, so the GUI can be chopped and changed -- as Dacta said, I'll probably try and find a KDE developer to port the GUI.

    Here is where the problems start: GNOME isn't just a GUI. I've been using several of the low-level APIs to handle, for example, internationalisation and persistant storage. Since I'm using OO, however, I can write simple, abstract classes, for example ProfileReader and ProfileWriter, which the calculation engine can use to load and save data to disk. I then derive classes like GnomeProfileReader and GnomeProfileWriter which are instantiated from the GNOME GUI and passed to the calculation engine. Presumably KDE has a similar facility for storing persistant configuration data, so whoever writes the KDE GUI can also make classes like KdeProfileReader and KdeProfileWriter - the calculation engine is unchanged.

    This moves the portability issues into the Makefile, leaving lots of lovely yummy #ifdef-free code.

    GUI diversity and OO helping out, posted 21 Dec 2000 at 20:01 UTC by pphaneuf » (Journeyer)

    I am probably not the only one to have noticed this, but badger's comment made me think about this again.

    About two years ago, Windows people were telling me how horrible and chaotic an environment I had, with GTK+ apps, Athena, Motif and apps using other widget sets were shown at the same time on my screen.

    They said that the unified widget set of Win32 made all their applications look and behave in similar ways, which was a Good Thing.

    Then I showed them FreeAmp (before x11amp/XMMS became popular), and how nifty of an interface it had, with its shaped windows and all. They dismissed it as a bad GUI which was not very intuitive and was difficult to navigate.

    Now, I do not use Windows PC regularly, but recently I went to one co-worker PC to listen to some music, a high-end Dell machine running Windows 2000, and I couldn't help but notice how much the very "modern" Sonique MP3 player looked a freakin' lot like my FreeAmp of many years ago. That same FreeAmp Windows people dismissed.

    And it wouldn't stop there. I'd say that at least half of its applications are using non-Win32-standard widgets, some in minor ways (newer Microsoft applications for example) and others in more major ways (Winamp, Sonique, and others).

    Now I'd love to corner one Win32 bigot: he'd have to admit one of two things. Either,

    • Linux lead the way to the future, did the "innovation" and Windows only followed later on, or
    • Windows is joining Linux to GUI hell.

    I don't know if I might survive such a discussion, either from me dying of laughter or from receiving schrapnel of Win32 bigot exploding from the paradox. ;-)

    dirtyrat: What you describe has common grounds with what XPLC is about, except that with XPLC, it can either be decided in the Makefile or at runtime, by the user or administrator. Isn't that great? :-)

    So objective that it hurts my eye., posted 21 Dec 2000 at 23:29 UTC by kjk » (Journeyer)

    Thank you for englightement, badger, and showing us the only true way.

    Now I know that FreeAmp, a copy of WinAmp, was innovative. And it continues to innovate. On my Fujitsu Laptop it cannot produce a decent sound under Linux staying way ahead of WinAmp under Windows which actually produces a sound I can listen to without a headache.

    I agree that Unix has a history of continuing innovation. X- Windows, for example, belongs straight to Guiness book for being the most bloated and unusable GUI on the planet. 10+ years and still counting. We shouldn't forget about X-lib, the most masochistic GUI library in the Universe. And when people thought that you can't produce even bigger crap X-Windows programmers gave us Motif. Let's not dismiss important innovation in "how to make the most unusable copy&paste operations" department and "we know no one makes this 3-button mouses any more but we came up with this innovative idea of pressing both mouse buttons to simulate the third. After 10 years of practice we found this to be real easy. It's time to innovate again". I've heard that they added scalable fonts to X-Windows lately. Woo-hoo!

    Now die laughing. Please.

    LyX and GUI-I, posted 22 Dec 2000 at 00:29 UTC by movement » (Master)

    I've been working on the Qt/KDE frontend to LyX, and in fact started the thread mrorganic refers to.

    First, it did not de-generate into "advocacy" issues. I can't recall a single point where someone said "you should use X toolkit because it's better than Y". mrorganic seems to badly mis-understand Matthias' point - not that "Qt roolz", but that the best thing for LyX is to concentrate on a straight port, rather than head for some kind of GUI independence. I can understand where he's coming from, but the fact remains that a separation of the frontend code can only be a good thing for the health of LyX's source code. I think this is definitely a good decision.

    Second, I find it quite odd that mrorganic seems to equate a GUI-I design with instability and LCD designs. I suggest he actually takes a look at the code in, say, a year's time, and compare it with the non GUI-I code, and ask himself which is more complex. I suspect he will find the new code a lot more readable and sane than the old.

    I should point out that LyX has *not* implemented anything approaching XUL, and it never will. Such a thing is a huge undertaking, as is evidenced by the current unusable status of Mozilla.

    And I really must take issue with mrorganic's claim that (and I quote) "Theory tells me that writing portable code should lead to better code, but experience has shown decisively otherwise". I would be very interested for him to give an example where non-portability has had a beneficial effect on a project's source code.

    egnor: I agree completely.

    atai: most portable GUI toolkits do have a severe LCD problem (as I mentioned, LyX isn't doing that). Apart from the Mac issue, I can't think of a good reason to not use either Gtk+ or Qt.

    jgg: your argument makes no sense. You are saying that portability has no benefit because people attempt to go about it in ugly ways (such as liberal #ifdefness) ? Sure, and comments are pointless because people write stupid comments ...

    And yet at the same time, you advocate targetting towards standardised platforms. No-one ever said that compatibility with 1982 UNIX was a good idea.

    Dacta: I hope you are aware LyX isn't a word processor ;)

    kjk: I had hoped trolls of your low calibre weren't around here.

    egnor has said everything I want to say about choice and diversity. In terms of LyX, the new approach is a hugely good idea, if only because it cleans up the code. A separation of Model and View/ Controller is always a good idea in GUI application code, and in LyX's case, GUI Independence is only a few small steps further.

    Missing the point...., posted 22 Dec 2000 at 17:20 UTC by mrorganic » (Journeyer)

    To movement:

    You (and many others) seem to miss the point I'm making entirely. The question is only peripherally about "freedom" -- the point is stability and maintainability. The poster-child for the failure of the cross- platform model has to be Mozilla (there's an example for you!): the development time and bug-count are exponentially larger than they would have been had Mozilla targeted a single platform API. AbiWord (as much as I like and respect those guys) is another example where stability has suffered due to cross-platform GUI support.

    As software becomes more and more mission-critical, it becomes less and less portable: most embedded software tends to be written very close to the hardware, and even software for critical environments (as eg medical monitoring software or air-traffic control software) tends to be *extremely* non-portable. I'm not saying this is a good thing (necessarily), just that it is necessary for stability.

    Note that I'm not saying that *all* portable software is unstable -- Berkeley DB is a good example of portable software that is also very stable. But when you throw GUIs and widget toolkits into the equation, things go to hell very quickly.

    if (portability != maintainability) return cruft;, posted 22 Dec 2000 at 20:01 UTC by rillian » (Master)

    The "theory" I'm familiar with is that writing portable code makes for more robust software because it makes you more aware of your assumptions and gets you think more clearly about how exactly you're doing things. For example, if you're writing endian-independent code it's harder to make off-by-one errors because you're thinking harder about where each byte goes and in a sense trying the code from two different directions at once.

    This is a distinct thing from API portability, and I think that's where the confusion comes from. Of course the principle applies somewhat, helping with design as you're aware of more than one way things can be done. But unlike the endianness example where you can just rewrite things in a (slightly longer) way that works everywhere, supporting multiple APIs means implementing the same functionality multiple times. That makes for a lot more work.

    If, as has been suggested, you factor things cleanly and use OO principles (rather than, say, #ifdef forests) you can at least localize the additional complexity in an interface. But (particularly until that interface is stable) it doesn't reduce the complexity of testing, and "works for me" doesn't go so far. Crystalspace is a good example, where despite good modular design, only a couple of the supported platforms work on any given day.

    The title wasn't meant to be perjorative. Cruft of course depends on what you've decided is worth supporting and interests differ.There's always a tradoff between supporting more platforms and simplifying your implementation.

    Xlib, posted 25 Dec 2000 at 17:50 UTC by sneakums » (Journeyer)

    Xlib is not a GUI library. It is a fairly direct C binding to the X protocol with some nice utilities thrown in. Expecting anything else will lead to pain and disappointment.

    Form follows function, posted 28 Dec 2000 at 05:33 UTC by apenwarr » (Master)

    The big mistake people always seem to make when writing portable programs is that they don't put in the portability at the right level.

    It seems to be impossible to make a portable user interface layer. In every program I've ever seen that tried this, you ended up with a lowest-common-denominator ugly interface that looked okay on, at best, one of the supported platforms. On all other platforms, it looked basically like it looked on its "good" platform. All the Windows programs now being ported to Linux via winelib will look like Windows apps no matter what, Mozilla looks equally ugly and non-native on all platforms, and Java... well, the closest they come to "Native widgets" is having Windows-looking buttons on Windows and Motif-looking buttons on Unix. Likewise with Tcl/Tk. That's not portability, and it certainly doesn't result in well-tuned, easy-to-use programs.

    Internet Explorer is an example of how efficiently you can program when you're writing platform-specific code. Microsoft produced (and continues to produce) IE very fast and it's actually very stable, at least when compared to any version of Netscape. Pity it crashes the whole OS when it dies, though.

    Netscape, until the Mozilla project, used to have totally duplicated (and, irrelevantly to this discussion, also very bad) code for the UI on Mac, Windows, and various forms of Unix. But at least it looked native -- Mozilla has much less UI-specific code, and now the UI is visibly non-native slower on all platforms.

    The correct place for abstraction is between the "functional" layer (which often can be completely portable, as long as the underlying system is mostly POSIX and ANSI C/C++) and the "interface" layer (which should be system-dependent if you want a UI that users actually like).

    The nice thing is, in most programs the interface layer is the easy part. Look at ghostview, gv, kgv, and the Gnome equivalent whose name I don't know. All of them use ghostscript, unchanged, as the functionality part, and write their own UI around it. It would be pointless to try to merge all four programs into the same source, because they've already been factored into their smallest functional components. If you tried to abstract them at a different level, you wouldn't be able to take advantage of xaw, Qt, or GTK widgets like you should. IMHO, ghostscript, gv, and kgv are at least 90% not duplicated code. They contain the code that's necessary to do what you want, using the native widget set.

    In my opinion, tasks like mail reading, network access, html rendering, file management, image manipulation, and so on should all be in nice, portable libraries or subprograms. If you do this, it becomes almost trivial to write the user interface parts -- that is, except for the time-consuming usability testing and tweaking, steps which almost everyone using a "portable widget set" skip anyway.

    As for writing a word processor in a widget set-independent way, you're basically out of luck -- almost all of the "hard" stuff in writing a WP is the UI tweaking. It matters very much what happens which menu items appear when you click on the File or Help menus, and users of different widget sets expect different things. Therefore, there needs to be a lot of different code for each widget set, or you'll never achieve ease-of-use. That said, standard (HTML?) renderers, standard file access routines, and standard network libraries across all the UI ports will definitely make it easier.

    Sorry about the long rant. I've worked on several "portable UI" projects before, I'm still waiting for a good Unix web browser, and the ever-increasing number of HTTP client implementations on my system is starting to get upsetting. I've written at least two of them myself...

    Quality follows quality, posted 29 Dec 2000 at 01:59 UTC by movement » (Master)

    apenwarr: I agree portability at the right level is vital. Most of the examples you present make sense (although, it is well-acknowledged that the finest version of MS IE is on a Mac platform - how do you explain that ?).

    The system you describe is pretty much what we are planning for LyX. I think it might even be possible to link the frontend at run-time, though I'm no expert on dynamic libraries etc.

    I've heard nothing but good things about Gecko. In what way does this not satisfy your requirement for a decent browser component ?

    gecko and MSIE, posted 29 Dec 2000 at 08:27 UTC by apenwarr » (Master)

    movement: As for MSIE/Mac, I think it's widely agreed that the most standards-compliant version of IE is the Mac version. (It still crashes all the time and doesn't render pages the same way as IE/Windows or Netscape, so "highest quality" depends on your point of view.) That's probably just because they rewrote it from scratch more recently so it's newer. Interestingly for this discussion, Microsoft didn't port IE to the Mac -- they rewrote it. And they did it with a rather small team of developers, really fast.

    As for Gecko: it's only problem might be that it's drowning in the rest of the Mozilla project. It lacks documentation, and it's apparently a lot of work to extract or build separately from all the stuff I don't want. It's not particularly extensible except perhaps with Javascript or by hacking the source. (Look at Konqueror to see what people want to extend their HTML widget to do... I guess they figured it was easier to write a new one from scratch.)

    Galeon, last I checked, wasn't a good enough UI to really be useable, though I agree it's way faster than Mozilla and the renderer works just as well, so it has a lot of potential.

    Also, it's completely impossible to use native widgets in Gecko, and if you look at the Mozilla mailing lists and documents, that was a design goal -- to make it easier on the web designer. That makes sense, but you get the same ugly, user-unfriendly buttons, checkboxes, and radio buttons on every platform, and they don't look right anywhere. They also don't hold a candle to the same widgets in any of Qt, GTK, Mac, or Windows, which all have had a lot more thought put into them. (FWIW, the Mozilla widgets have improved dramatically in recent months, but it's the tweaking that makes the difference, and it will take many more months to even begin to approach the quality control in GTK widgets, let alone Mac ones.)

    Gee, I'm usually a big portability geek, because I often see people doing obviously silly things like assuming the size of 'int' or writing their own mouse code instead of using gpm, and that sort of thing can be easily fixed. Big, complex UI stuff is hard to do portably, though, so I tend to advocate against it.

    Microsoft always makes a great portability counterexample, though I guess assuming the size of 'int' backfired on them too :)

    New Advogato Features

    New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

    Keep up with the latest Advogato features by reading the Advogato status blog.

    If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!

    X
    Share this page