New essay: Trying to convince application developers to write API documentation

I’ve written a new short essay: Trying to convince application developers to write API documentation

I’ve created the Short essays page on my website. I plan to write more essays in the future, as short articles that can be read independently. Around the theme of programming best-practices. I’ll inform you on my blog when I publish a new essay.

Note, it’s unfortunately not written in ConTeXt (see this previous blog post), as I haven’t found a text editor for ConTeXt that just works and is easy to install, with all the features I’m accustomed to when I write a LaTeX document. So I fell back to using LaTeX.

The art of using GSettings in a library

While providing GActions in a library can be done quite naturally, for GSettings it is more complicated.

To simplify, GSettings is used by GTK applications to store their settings. Libraries usually provide GObject properties, and the application can bind the properties to the corresponding GSettings key with the g_settings_bind() function. So far so good.

For the libdevhelp I wanted to go one step further, and provide a GSettings schema in the library itself.

Taking a step back – why?

It is no secret that the goal is to create a software product line. By being able to create new API browsers super easily. But there is already the Devhelp application, you say. Yes, and currently that application is still generic, it is suitable for any development platform as long as the API references follow a certain format (HTML pages plus a *.devhelp2 index file). But more features could be added to Devhelp, like downloading the API documentation for a certain development platform, or having a start page with the most common libraries. If those features are added directly to the Devhelp application, for the GNOME development platform, then the Devhelp application would no longer be suitable for other development communities, and we prefer to keep the door open.

So if several API browsers products are created on top of the libdevhelp, it would be nice to avoid work duplication, and this includes the GSettings handling.

Handling GSettings in a library

Who says GSettings says creating a GSettings schema. Who says GNOME library says parallel-installability for the different major versions of that library. Thus, the GSettings schemas must also be parallel-installable. Little problem: when migrating to a new major version, the user doesn’t want to lose all his/her settings.

And here is one thing that – in my humble opinion – GSettings doesn’t handle well: keys and settings migration. With the GSettings API the schema needs to be installed. In the situation of a migration, the old schema is usually not installed. So it’s a bit more difficult to get the values for the old keys.

Settings migration can be useful for applications too, when wanting to do refactorings in the GSettings schema, for example when renaming a key. Or when renaming the whole application.

The solution in the libdevhelp: have a relocatable schema. At runtime the schema is relocated to the desired path. And I’ve written a small utility, DhDconfMigration, to migrate individual keys when dconf is used as the GSettings backend (and now Flatpak applications are moving away from dconf, but the same principle can be applied to other GSettings backends). DhDconfMigration is currently used by GNOME LaTeX to migrate the settings from LaTeXila (the application has been renamed). But DhDconfMigration (or the same kind of utility for another backend) is not yet useful for the libdevhelp, it was written to ensure that migrating keys is possible if the need arises.

Another thing that I wanted to solve in the libdevhelp with regards to the GSettings handling: make the use of GSettings optional for certain keys, when an application doesn’t want to provide a setting for a certain feature. In that case, it’s the same as using a simple GObject property. So binding the property to the GSettings key is optional.

The result

The above explanation is maybe a little complicated, and you may think that putting GSettings in a library is over-engineered, but using the resulting libdevhelp API is actually very simple, and it simplifies the application(s) implementation, so all is good, right?

For those interested, I’ll let you browse the gschema and the API reference of DhSettingsBuilder and DhSettings. It uses the builder pattern described by Benjamin Otte. Other classes and widgets in the libdevhelp use DhSettings to access the settings. The solution is not perfect, there is room for improvement, but I think it’s a good enough solution. And good enough is.. good enough 🙂 The source code contains more comments and improvement ideas.

Providing GActions in a library

Yes, it’s possible to provide GActions in a library, to have more code re-use across similar applications (a recurrent topic on this blog and the work that I do in GNOME).

Tepl (Text editor product line) provides GActions in its public API. It’s nothing new, it’s been there since several years, but at the time when I added those GActions in Tepl I remember that I was quite excited with the achievement 🙂 Let’s take a quick look.

GActions in a library

GAction represents an action that the user can do in an application, it’s usually present in a menu item or a button. It’s not just a function to launch, it’s a little more involved than that.

Overall, providing GActions in a library can be done quite naturally, once the library provides a framework for the application.

TeplApplication and TeplApplicationWindow both provide GActions in their public API. They are namespaced with the "tepl-" prefix, to avoid conflicts with other libraries or the application; so the full name of the GActions are "app.tepl-something" or "win.tepl-something". And all the GActions are documented in the class description.

Note that TeplApplication and TeplApplicationWindow are not subclasses of GtkApplication and GtkApplicationWindow, because several libraries might want to extend those GTK classes and an application needs to be able to use all those extensions at the same time. A nice solution that doesn’t require to hold a new object in the application: use this design pattern that I’ve already described on my blog.

Sharing best-practices

If you know or if you’ve implemented kinda the same in another library, I’m interested to hear about it. To see how it’s handled elsewhere, to have more code examples to be inspired by.

Next topic

Providing GSettings in a library. Done in another project. Topic for a next blog post 😉

LaTeX or ConTeXt for writing documents

I’ve started to learn a little ConTeXt, a language for writing documents. It is similar to LaTeX, but is easier to manage.

To quote a former user of GNOME LaTeX who has filed a feature request to add ConTeXt support:

“It includes about all packages you probably need, so in most cases, you won’t need additional ones – and thus don’t have package rivalries at all! Furthermore it’s much more consistent, way more convenient and also more powerful.

I did my bachelor’s thesis with LaTeX and my master’s thesis with ConTeXt – which was SO MUCH more comfortable than LaTeX, that I won’t use LaTeX anymore at all.”

If I wanted to re-implement GNOME LaTeX, it would target the ConTeXt language instead. If there are any ConTeXt user reading this, I would be interested to know what application you use for writing ConTeXt documents, and what features are important to you. If I have the time and funding, I’m interested to implement such a “ConTeXtedit” app that Just Works, out-of-the-box.

Additional links:

Back to University

I stopped my master degree 6 years ago, partly because it was not compatible with open-source development (doing both at the same time was not realistic, and guess what I liked most). And with a bachelor degree that is worth something on the job market, I was able to apply to job offers and start working, and that’s what I did. But I now regret it, I was not satisfied by my day job, and when I see job offers requiring a bachelor degree in Belgium, most of the time I’m not interested.

So, I’ve taken the hard decision to start again studies, to finish my master degree in computer science!1) It’s a bit strange to go again to courses, studying etc. But I’m re-adapting.

In my last blog post I said “back to GNOME development”, but this time around my studies are the priority. And to avoid stress/burnout, I try to no longer work the evenings and weekends, so it drastically limits my time that I’ll devote to GNOME.

Footnotes   [ + ]

1. At the UCLouvain University, in the modern and pedestrian city of Louvain-la-Neuve, Belgium (link to the gastronomy page, the most important thing 🙂 ).

Back to GNOME development

After writing my last blog post – a retrospection about my first 10 years of Free Software development – it made me want to contribute to GNOME again. I didn’t contribute much this past year (in short, too much stress). But I’m back, I hope my keen interest will continue.

I’ve restarted with gedit. I’m improving the documentation for contributors, I’ve written a new roadmap, and done the 3.33.92 development release. Plus already a small yak shaving in jhbuild (doing the release) for the gedit contributors’ docs 🙂

10 Years Later

10 years ago, in 2009, when I was 19 years old, during the summer after my second year at the university, I started to develop a new Free/Libre desktop application for GNU/Linux for writing LaTeX documents, now called GNOME LaTeX, based on the GTK GUI toolkit.1)

I quickly realized that the plumbing for developing such an application was lacking. It required to re-invent the wheel, basically re-implementing the core of gedit (50k lines of code back then, without counting the plugins, to have a top-notch implementation). There was the GtkSourceView library – used by gedit – but it was far from sufficient. What I did for GNOME LaTeX is to have a much simpler implementation than the gedit core, leaving out some features and have a lower quality for the essential features.2)

That’s why 2-3 years later I got involved to improve GtkSourceView, and to kickstart a project to make the gedit source code more re-usable.

A decade later, all my GNOME projects

The result, including some side projects:

  • I’ve improved a lot GtkSourceView, receiving very good feedback from application developers.
  • I’ve created 3 other libraries: gspell, Tepl and Amtk.
  • I’ve created in total 3 GTK text editors: GNOME LaTeX, gCSVedit and Gnotepad.
  • I’ve contributed extensively to gedit, Devhelp and its libdevhelp.
  • I’ve contributed a little to GLib and GTK, including the addition of some small APIs.
  • I’ve started to write the book The GLib/GTK Development Platform – A Getting Started Guide, for the C language (70 pages currently).
  • And other yak shaving and side projects: gnome-c-utils, a brochure on GLib/GTK for the FOSDEM conference, and of course some contributions to other GNOME modules.
  • Andthen:
    • Error: not enough funding.
    • Too much stress, I needed to rest.

The gedit codebase has shrunk, but not as much as I would like. It stems from the fact that the gedit core provides an API for plugins, so either the API must remain intact, or when breaking the API the official plugins need to be adapted, and lots of third-party plugins would be unavailable during possibly a long time. So it complicates matter significantly when wanting to do big refactorings in the gedit core.

Statistics

Just counting my GNOME or GNOME-related projects:

  • 6200 Git commits.
  • Author of ~140k lines of code, according to git blame in *.{c,h,vala,py} files (the vast majority being C library code).
  • Contributions in more than 30 GNOME Git repositories.
  • Some modules that I maintained or created are installed on millions of computers worldwide, thanks to being installed by default with GNOME.

A vision – Developing software product lines for GNOME

In short, my focus in GNOME is to make more code re-usable, especially in the field of text editors and other developer tools. The code is written as a set of object-oriented libraries. At most flexible at best.

It’s very similar to the “as a library” philosophy of the LLVM compiler infrastructure project:

“A corpus of functionality built as a set of libraries that can be sliced and remixed in different ways per the needs of different use-cases.” (Chris Lattner, original co-author of LLVM)

And it enables new possibilities: create software product lines! Instead of developing one application like gedit, the idea is to be able to develop a set of similar applications, each specialized for a different use-case. GNOME LaTeX is specialized for writing LaTeX documents, gCSVedit is specialized for CSV/TSV files, etc. There is still a need for a general-purpose text editor like gedit or Gnotepad, when a specialized text editor has not yet been developed.

A specialized application – by definition – has the potential to be better at its targeted task. Ideally, the application Just Works out-of-the-box, without the need to spend a lot of time to configure the application, finding plugins, etc.

This vision can be applied to many situations:

  • For text editors as previously explained.
  • I’ve almost finished to implement it for the Devhelp API browser, to be able to create specialized API browsers for specific development platforms.
  • For other desktop environments that prefer a traditional GUI instead of the more modern GNOME GUI for applications: from the same codebase (a library), create two applications, one with the old GUI and the other with the new GUI. This would permit to avoid forking the code or writing new applications from scratch.
  • For the desktop itself: create a software product line to be able to develop easily new desktops like gnome-shell.

Writing almost all the code as re-usable code is harder, but it is always possible: it is just software after all. And a well-designed library has a cleaner codebase and is easier to understand thanks to its API documentation.

Revisions

  • 2019-08-23: Add section about the vision with software product lines and specialized applications. Remove less important paragraphs to not make the article too long.
  • 2019-08-25: Add more details and a second footnote to the introduction.

Footnotes   [ + ]

1. The idea to develop a desktop application – instead of some other kind of software – didn’t come out of thin air. In primary and secondary school I did web development, but I no longer wanted to play in that field. During the second year at the university, we needed to develop a desktop application in Java by groups of two, and I enjoyed doing that project. During the summer vacation, it made me want to develop my own desktop application, and since I liked GNOME 2, I wanted my app to be well integrated with GNOME, so I chose to develop it in C with GTK. And now, look where all of this has led me!
2. I didn’t want to fork gedit because it would have duplicated the maintenance, and as a total beginner back then I had difficulties to understand some of the gedit code, because I didn’t know well the GObject library.

Expanding Amtk to support GUIs with headerbar

I initially created the Amtk library to still be able to conveniently create a traditional UI without using deprecated GTK+ APIs, for GNOME LaTeX. But when working on Devhelp (which has a modern UI with a GtkHeaderBar) I noticed that some pieces of information were duplicated in order to create the menus and the GtkShortcutsWindow.

So I’ve expanded Amtk to support GUIs with GtkHeaderBar and GtkShortcutsWindow, and ported Devhelp to Amtk. I’m quite happy with the result, there are fewer lines of code, it avoids information duplication, all the extra information about the GActions are centralized (so inconsistencies are easier to catch), and on top of that Amtk has been designed to be able to share the extra GActions information in a library, so it’ll be possible to provide a higher-level API for the libdevhelp.

Read the Amtk introduction for more details.

PS: oh, and I’ve moved Amtk to its own git repository now, it was initially developed inside Tepl.