Object-oriented design best practices

August 27th, 2014 by swilmet

Here is another book review, this time about object-oriented design.

Programming Best Practices

We can learn by our own experience, we can use our common sense, we can learn by more experienced developers when contributing to an existing project. But to speed things up, reading a good old book is also a good idea.

For programming in general, not specifically for object-oriented design, see the blog post About code quality and maintainability.

Object-Oriented Design Heuristics

For OO design, the well-known Design Patterns book is often advised. But most of the design patterns are not often applied, or are useful only for big applications and frameworks. How often do you create an Abstract Factory or a Facade?

On the other hand, the book Object-Oriented Design Heuristics, by Arthur Riel, discusses in details more than 60 guidelines − or heuristics − that can be applied to all projects, even for a small codebase with three classes.

Example of an heuristic:
Keep related data and behavior in one place.

If a getter method is present in a class, why is the data used outside of the class? The behavior implemented outside of the class can maybe be implemented directly in the class, so the getter can be replaced by a higher-level method.

Other example:
Distribute system intelligence horizontally as uniformly as possible, that is, the top-level classes in a design should share the work uniformly.

By following this heuristic, god classes should be avoided. An example of a class that can be split in two is where some methods use only attributes A and B, while some other methods use only attributes C and D. In other words, if a class has non-communicating behavior, that is, methods that operate on a proper subset of the data members of the class, then the class can be split.

All the heuristics can not be followed all the time. That’s why they are called “heuristics”. But when an heuristic is violated, there should be good reasons behind that decision, and the developer should know what he or she is doing.

Event-driven programming

One missing concept in the book is event-driven programming.

With GObject, we are lucky to have a powerful signal system. It is a great way to decouple classes. When an object sends a signal, the class doesn’t know who receive it.

Conclusion

Programming best practices are useful to maintain a good code quality. Object-Oriented Design Heuristics will give you the knowledge to better write object-oriented code, either for small projects, big projects or API design in a library.

File loading and saving in GtkSourceView, finally

July 9th, 2014 by swilmet

Last year GtkSourceView saw a new search and replace API. This year it’s the file loading and saving that has just landed! It is in the continuity of making the gedit source code more reusable for other text editors.

In short, the back-end part of the file loading and saving in gedit has been moved to GtkSourceView, with a new and more flexible API to better wrap the feature. The code has been modified to follow GIO conventions for asynchronous operations, to use GTask internally, and replace the uses of GSettings by properties, among other things.

The file loader auto-detects encodings, newline types and compression type (yes gedit can open gzip files). Invalid characters can also be displayed with their corresponding hexadecimal value, because GtkTextBuffer accepts only valid UTF-8 text. And progress information is reported during the operation.

The API is stateful: the file parameters (encoding etc) are remembered between a file loading and a file saving in a GtkSourceFile object. Unfortunately the new API is still quite low-level. The application must configure the file loader and the file saver, and some errors are returned to the application.

So the front-end and errors handling is still implemented in gedit. Errors and progress information are displayed in an info bar, above the GtkSourceView widget. For some errors, gedit proposes different actions to the user, like choosing another encoding.

API design

If you are a text editor developer, don’t hesitate to have a look at the GtkSourceFile API. The API can still change during this 3.13 development cycle. The notes about the API design are available on bugzilla (there has been four iterations). Here is a summary.

The API is a bit heavy, with the following classes: GtkSourceEncoding, GtkSourceFile, GtkSourceFileLoader and GtkSourceFileSaver. There are good reasons for having two class’ names derived from a verb (“to load” and “to save”), which is generally a hint that those classes should be replaced by a method (i.e. an action). The reasons are partly similar with the new GSubprocessLauncher in GIO: the FileLoader and FileSaver classes are there not only for launching the operation, but also for configuring it with a nicer and more extensible API than one function with a dozen parameters. With the FileLoader and FileSaver, we can add properties, functions and even signals. And the FileLoader and FileSaver classes are quite useful in gedit: when an error occurs and the user clicks on a button in the info bar, the loader or saver object is reconfigured and the operation is relaunched, without the need to keep the initial configuration around. Also, the FileLoader or FileSaver properties are applied to the GtkSourceFile object only on a successful operation, so the GtkSourceFile state is (normally) consistent with the underlying file on the disk, at least at the time of the last load or save done with GtkSourceView.

Possible follow-ups work

A possible follow-up is to make the front-end code more reusable, either by creating higher-level classes in GtkSourceView, or by creating a git submodule, like the libgd (without API stability guarantees in the latter case).

Another possible follow-up is to analyze and improve the performances, which are currently quite bad. For short files it is not visible of course, but opening a very big log file takes more time than with other popular text editors.

There are other possible improvements, like unescaping invalid characters when saving, or avoid blocking the GtkTextBuffer when (auto-)saving a short remote file on a slow network connection.

Changes for gedit plugins

Unfortunately there are some changes in the gedit API for plugins, mainly in GeditDocument. Fortunately the changes are well documented, and most plugins should still work without any modification.

Conclusion

The file loading and saving can quickly become a fairly complex beast. Now this code is available for other GTK+ text editors.

Thanks to Paolo Borelli for the reviews!

TL;DR:

  • In GtkSourceView: 29 files changed, 7909 insertions(+), 3 deletions(-)
  • In gedit: 49 files changed, 1888 insertions(+), 8819 deletions(-)
  • In gedit-plugins: 11 files changed, 22 insertions(+), 31 deletions(-)

This is a 12% code increase in GtkSourceView, and a 6% code decrease in gedit.

PS: As usual, some tests would be more than welcome before the stable version in September.

Making the gedit source code more reusable

May 20th, 2014 by swilmet

On IRC I see some developers working on other text editors based on GtkTextView/GtkSourceView. It is a good thing in my opinion to have specialized text editors. They are easier to use and configure. A specialized application has a potentially better usability. A general-purpose text editor like gedit is of course still needed for languages not covered by a specialized text editor or IDE.

The problem is that creating a new text editor based on GtkSourceView is still quite a lot of work. Instead of reinventing the wheel, the idea is to make the gedit source code more reusable by moving it to GtkSourceView or to a git submodule. This wiki page has all the details, it keeps track of the progress made (see also the RoadMap), more details on the “why?”, and a paragraph on Anjuta.

This blog post was to make developers aware of this initiative. If you are interested, join us on the #gedit channel or the mailing list!

{specialized, general-purpose} × {text editors, IDEs}

February 11th, 2014 by swilmet

Some thoughts about text editors, IDEs, specialized or general-purpose applications.

Several languages Other tasks Plugins
Specialized text editor No No ?
General-purpose text editor Yes No Yes
Specialized IDE No Yes ?
General-purpose IDE Yes Yes Yes

The above table summarizes how I view the text editors and IDEs field.

Several languages

A specialized application focus only on one programming language, or several languages used together. A general-purpose application can support completely different programming languages and platforms.

Other tasks

A text editor focus only on editing text or source code, while simplifying as most as possible the writing of this code. An IDE integrate other features like building the source code, running it, writing commits, integrate a debugger, and so forth.

Plugins

For obvious reasons, a general-purpose application should have a plugin system. For a specialized application, the need for plugins is less obvious.

Two extremes

The general-purpose IDE with plugins is one extreme. The user interface must be generic enough to suit plugins and different programming languages. And it takes more time to learn and configure the application.

The specialized text editor without plugins is the other extreme. The developer has full control on the user interface, so the application has a potentially better usability. The application requires less time to learn and configure. Ideally, it should Just Work.

Not reinventing the wheel for specialized applications

Write libraries for the common features! Or at least ensure that your code is reusable. This is not limited to text editors and IDEs, I’m sure you can apply the same principles on your favorite field.

Search and replace behavior for a text editor

December 8th, 2013 by swilmet

The search and replace is one of those features that have a wide variety of different implementations and behaviors across applications. The nice thing with my work I did this summer on GtkSourceView, is that you can build whatever behavior you want by using the search and replace framework. And that’s exactly what I did for LaTeXila, which has a new behavior for the replace button.

Search and replace in LaTeXila

Search and replace in LaTeXila

When we replace an occurrence, we generally have the time and we don’t have a train to take (or we are already in the train). And it’s better to see how the content looks like with the replacement text, to see if everything is fine and make adjustments if required. As a consequence, when you click on the replace button, it just replaces the search match without moving to the next occurrence (which can be far away, so we would not be able to see the replaced text).

When you have just replaced an occurrence, no text is selected. If you click a second time on the replace button, it goes to the next occurrence, and selects it, to repeat the process. Nice, isn’t it?

Voilà, that’s all, I just wanted to share this information. It can be interesting for other applications.

The GSoC on GtkSourceView/gedit comes to an end

September 21st, 2013 by swilmet

A small update on my GSoC.

The first part took a little longer than expected. But I’m happy with the results, the search and replace API is simple and flexible, there were not a lot of bugs to fix, and gedit users will be happy with the improvements (including the regex search).

I’ve changed a little what was initially planned for the second part of the GSoC. Ideally, it was to rework the color schemes to use CSS, and investigate GtkTextTag to modernize it. For the color schemes, it was not really a high-priority issue for GtkSourceView, writing them in XML works fine. And the GtkTextTag investigation would have been the logical follow-up. But with the remaining time, I have found other interesting and smaller tasks instead.

The past few weeks I worked on various things in other parts of GtkSourceView and gedit: better document the API, fix some bugs, improve the code here and there, and investigate two longer projects: the code folding and making the gedit source code more reusable.

I’ve written a utility class to navigate quickly through a set of GtkTextMarks. It is a cleaner implementation of GtkSourceMarks, and it will be useful for the code folding.

Making the gedit source code more reusable

For making the gedit source code more reusable, I’ve created a git submodule called libgedit. Like the libgd, the API/ABI stability is not guaranteed. The purpose is to try to move as most code as possible in the libgedit, iterate the API if needed until it is good enough to be included in GtkSourceView. So the libgedit would be a staging area between gedit and GtkSourceView. There is a problem though: gedit has an API for its plugins. And if possible, it’s better to not break the plugins… If the code moves from gedit to the libgedit, and then from the libgedit to GtkSourceView, there can be several API breaks. On the other hand, if the code goes directly in GtkSourceView, there is at most one API break (that can be avoided if the gedit functions are simply deprecated, not removed). With the second solution, the risk is to discover problems too late.

Maintaining the gedit plugins API in the libgedit is one problem. There are other problems: it would be nice to share the translations; have an API documentation only for the libgedit (with GTK-Doc, I mean); working with a git submodule is less convenient; having the same namespace (“Gedit”) for gedit and libgedit is a problem when trying to make the code more reusable; a headers nightmare, some headers are private, others are public, and others are split between gedit and libgedit; and so on.

So I think it will be simpler to move the code directly to GtkSourceView. The API must be well thought. The developers must have enough time during the 6-months development cycle to iterate the API if needed. And ideally the API must be tested on other applications than gedit. If it is done slowly but surely, by small steps every cycle, it should be doable.

That’s all folks. Thanks to Ignacio Casal Quinteiro (nacho) and Paolo Borelli (pbor) for their reviews, advices and (sometimes late ;-) ) testing. Thanks to Garrett Regier (gregier) for having well tested the new search and replace in gedit. And thanks to Google and GNOME, for accepting me as a GSoC student.

Regex search in gedit and GtkSourceView, finally

August 19th, 2013 by swilmet
Regex search in gedit

Regex search in gedit

Although regular expression searches were possible with plugins, it is now available by default in gedit. The search and replace works too, and you can use backreferences (\0, \1, …) in the replacement text.

All this work has been merged upstream, just in time before the freeze.

Reworked search and replace API in GtkSourceView

Behind the scene, the regex search is implemented in GtkSourceView. For most cases, it scales well for big text buffers, since multi-segment matching is done: when a partial match is returned, we take a bigger segment. Read the lengthy implementation overview at the top of gtksourcesearchcontext.c for more details.

Besides the regex search, the API is now more flexible. Roughly speaking, it was initially a one-to-one relationship: only one search was possible at a time in a text buffer. It is now a many-to-many relationship: several searches can execute at the same time in the same text buffer (it can be useful for non-highlighted, background searches). And the search settings can be shared between several buffers.

Next step for my GSoC: rework the GtkSourceView style schemes to use CSS.

Align parameters of a C function declaration, with lineup-parameters

July 25th, 2013 by swilmet

Renaming a GObject class can involve a lot of manual work. Once the type is renamed, the parameters of the function declarations are no longer aligned. In the following example, GtkSourceSearch has been renamed as GtkSourceSearchContext:

guint
_gtk_source_search_replace_all (GtkSourceSearchContext *search,
                                const gchar     *replace,
                                gint             replace_length)
{
        /* ... */
}

It is a GNOME convention to align the parameters, so the code must be fixed:

 guint
 _gtk_source_search_replace_all (GtkSourceSearchContext *search,
                                 const gchar            *replace,
                                 gint                    replace_length)
{
        /* ... */
}

As programmers, we don’t like doing such a manual work, and even less when we are renaming a big class. Unfortunately, the Indent program doesn’t have an option for that. If you use Vim, there is the Align plugin, that have the \afnc alignment mapping. But it doesn’t align the parameters on the parenthesis.

So I wrote a script! The result is in my gnome-c-utils repository (containing only the lineup-parameters script for the moment).

To detect the parameters, a few regular expressions are used. There are quite a lot of restrictions, but it should work for most GNOME software. To have a perfect script, libclang could be used, but I’ve never used it, so regular expressions was a quicker solution.

The script can be used to convert an entire file, or can be used from a text editor (stdin is read, and the output is written to stdout). I’ve documented how to add a key binding in Vim. So by pressing a single key, the parameters are correctly aligned!

This is just a small step to improve the developer experience in GNOME. But I hope this will be useful for other developers. I dream of a GNOME C IDE that handles the boilerplate (for renaming classes too), that aligns the parameters and the function prototypes in the headers, with auto-completion for signals and properties names, and so on.

Search and replace in gedit and GtkSourceView

July 15th, 2013 by swilmet

My GSoC on GtkSourceView/gedit/… is coming along nicely. Here is a screenshot of the new search in gedit:

New gedit search

New gedit search

The visible new thing is the “298 of 703″ in the search entry, that shows the position of the current search match, and the total number of occurrences. This is just the tip of the iceberg, as much of the work has been done under the hood. Ignacio (nacho), my mentor, has improved GdTaggedEntry, and I worked on the new API in GtkSourceView, and adapted gedit to use the new API.

Note: almost all my work has already been merged upstream, but not the new search entry.

Search and replace API in GtkSourceView

The new API in GtkSourceView is available. One thing is missing though: regex search.

Why you should use this API:

  • It is asynchronous, i.e. the user interface is normally not blocked when the GtkTextBuffer is scanned. And the asynchronous overhead is small;
  • The search matches are highlighted;
  • You can get the total number of occurrences and the position of a certain occurrence easily;
  • For each search, the buffer is scanned at most once. Once the search occurrences are found, navigating through them doesn’t require to re-scan the buffer, thanks to gtk_text_iter_forward_to_tag_toggle(). As a result, most operations are really fast;
  • The regex search (still to come) will normally do multi-segment matching, also called incremental matching: when a partial match is returned, we take a bigger segment. No need to waste memory space to retrieve the entire buffer contents.

Nice, isn’t it?

Developing graphical IDEs the UNIX way

July 3rd, 2013 by swilmet

Programming on a UNIX environment generally involves the use of command line tools: vim/emacs, git, grep, sed, screen/tmux, and so on. What is really nice about these tools is that they do only one thing, but do it well. Now, what about people not wanting to learn shell commands? And sometimes (sometimes), graphical interfaces are more convenient.

An IDE is an integrated development environment. What people think about this “environment” is generally a bloated program (*cough* eclipse *cough*). But what if the environment is not one big application, but several small programs? The small programs can interact a little together through D-Bus, if needed.

Let’s take a few examples.

Specialized text editors

To have a good user experience, the text editor should be smart enough to know the language used (C, C++, Python, Vala, LaTeX, etc.) and implement features specifically for the language. A few examples:

  • Code completion;
  • Switching between the call of a function to its definition;
  • Have an overview of the file (the list of functions, or the structure of a LaTeX document).

Having only one text editor for several types of tasks (C and LaTeX for instance) is not convenient. It works with vim or emacs, but at the cost of passing lots of time in the configuration files. If a graphical application have thousands of settings, we end up with something worse than eclipse. No, instead, there should be one text editor for each task. And one another general-purpose text editor that don’t include specialized features.

This is not just about settings. With a single text editor for all tasks, the UI must be generic enough for the plugins, but they will always be restrictions. On the other hand, with an independent application, the UI can be exactly what is needed: not too generic nor too restrictive.

The common features between all those specialized text editors can be shared in a library. A project is to make the gedit source code more reusable. It would have been a nice GSoC for me (see this draft proposal for more details), but instead I work on GtkSourceView, which is also nice.

git

Working on a git repository can be a bit difficult at the beginning. A graphical application that implements the basic features can be useful for some people. But it doesn’t need to be available in the same program as the text editor!

Creating a commit, navigating through the repository history, pull, push, changing branches, … have nothing to do in a text editor, in my opinion. There are some things that can be useful in the text editor though: if there is an integrated file browser, we can mark the modified/added/removed files. And in the margin of the text content, we can mark the modified sections.

Search and replace

The search and replace in a text editor can be limited at one file at a time. The search and replace entries can be shown in the top-right corner of the file, with a little button to show and hide the replace entry.

The search and replace in multiple files is another beast. Integrating it nicely in the text editor is a difficult task. Generally the developer choose a dialog window, because it is the best available option, but it partially hides the file contents…

Why not a small application that do only that? It would roughly select a directory, and search in all files in this directory. The text editor can have a menu item “Advanced search and replace” that would launch the small program with some parameters. The advantage of this small program is that the UI is really better, since it doesn’t have all the text editor features.

When we replace some text, sometimes we want to do small modifications afterwards. But normally, the specialized text editor features would not be needed in the small search and replace application.

The specialized text editors would already have features to edit several files at once. For example, when we change the name of a function, all the calls to the function can be renamed too, and adjusting automatically the indentation of the parameters (should be doable).

Conclusion

The general idea is to have small programs with a clean and simple UI, which don’t require lots of configuration, and that work well together. Ideally, they should Just Work™, like other GNOME applications.