Cyclomatic complexity in GIMP code

After reading Xan’s article The Cyclomatic Horror From Outer Space analyzing the complexity of some GTK functions, I was curious and I wanted to run the same test in the GIMP source tree in order to see what parts of the code would be the hardest to test. This test is very simple and can be summarized as counting the number of decision points in every function in a program (so you get an idea of the number of possible code paths).

I did as suggested and I started with “apt-get install pmccabe“, followed by “pmccabe app/*/*.c | sort -nr | head -10” to get the 10 functions with the highest (worst) results. This gave me the following table:

Cyclomatic complexity Lines of code Function name
113 892 gimp_display_shell_canvas_tool_events
100 123 layers_actions_update
69 416 update_box_rgb
61 359 border_region
60 445 siox_foreground_extract
56 452 render_image_tile_fault
54 327 combine_inten_a_and_inten_a_pixels
53 194 gimp_plug_in_procedure_add_menu_path
47 275 gimp_drawable_offset
46 240 gimp_vector_tool_oper_update

According to the CMU page on cyclomatic complexity, numbers between 21 and 50 reveal a “complex, high risk program” and numbers above 50 only occur in an “untestable program (very high risk)“.

What does this mean for GIMP? Not much. But if you touch one of these functions, please be careful… you might break things and it will be very hard to find where the bugs are hiding in that code.

Features and remote controls

Jimmac posted a very interesting journal entry about “more features” and a comparison with remote controls. I thought about it a bit and started typing a comment to his blog, but as it grew longer and longer I decided to move it here so that I have a bit more space…

This nice comparison with a remote control made me think about how I use mine. The device that controls my TV (and VCR) has a little flip hiding the “advanced” buttons. I do not have a photo of my remote control, but I found one that is reasonably similar. The top part until the red power button can be opened to reveal more buttons.

The basic buttons such as channel selection, volume and start/stop for the VCR are always visible. If you lift the flip, you get extra buttons for selecting input sources (e.g., DVD player or camera) or outputs, changing the parameters of the display and other exotic stuff. As it turns out, two of the “advanced” buttons on my remote control are as worn out as the channel and volume selection buttons that are among the “normal” buttons. So I am very glad that these buttons exist, otherwise the device would have been far less useful to me. On the other hand, I understand that they are hidden under a flip because some other people (whether they are a majority or a minority is irrelevant) would probably never use them. Even myself, I do not need to see all buttons all the time.

The comparison with this little device that I use almost every day is very interesting to me. And I take some lessons from it: the designers of this device could not predict which buttons I would use most frequently. They modeled this device for a slightly different class of users, yet I enjoy using it because the “advanced” buttons that I need are still within reach when I need them.

In case you cannot guess where I’m heading yet, let me add that the “advanced” buttons are not visible by default so that they do not confuse those who do not need them, but they are easily discoverable and once you get to them, they look and behave exactly like the other buttons. I do not need to open my TV and flip a few DIP switches to get to the advanced options. Translated in the GNOME or GIMP world, this means that I would have a default set of features that I can play with but also some advanced settings that are easily accessible from the application without having to resort to some other obscure tool such as a gconf editor.

I do not really need to have “everything at my fingertips” and be confused by huge configuration dialogs for every little feature. In fact, I prefer to have the less frequently used options hidden away, as long as there is an easy way to access them whenever I need them. It is essential for these advanced options and features to be discoverable, so the dialog that contains the basic options should give a visible hint that more stuff exists but is hidden (using an expander for the dialog or an “advanced options” button or whatever).

Also, even if I do not use some of the other “advanced” buttons on the remote control, I do not think that I would have bought that TV set if I had not seen that these options were available.

Update: moved the image and its description up a bit.

Back from GUADEC

GUADEC 6 in Stuttgart was a great event, as expected. Compared to the first GUADEC in Paris, some things were a bit different (the way the event was organized, the number and size of the sponsors, the keynote speeches, etc.) but many things were the same (great hackers presenting their stuff, great discussions after the presentations). Talking with people was probably the most important part of that event: meeting other GIMP developers and also some hackers that I had not met before. Now that I have recovered from the party(ies) and lack of sleep, I could write a lot about GUADEC. But instead, I will make it short and just say that it was a lot of fun.

I came back from GUADEC with more than 600 MB of photos. I still have to find a way to publish them somewhere, in case some people would like to see their pretty faces (or not so pretty, especially after the party). Anyway, I will take care of that when I am back from vacation and from a business trip, so that will not be done in the next two weeks.
{"cc_re__cc_re__cc_by_sa_3_0": ["ontent -->\n\n\t<footer id=\"colophon\" class=\"site-footer\" role=\"contentinfo\">\n\t\t<div class=\"site-info\">\n\t\t\t\t\t\t<a href=\"https://wordpress.org/\">Proudly powered by WordPress</a>\n\t\t</div><!-- .site-info -->\n\t</footer><!-- .site-footer -->\n\n</div><!-- .site -->\n\n<img alt='css.php' src=\"https://blogs.gnome.org/raphael/wp-content/mu-plugins/cookies-for-comments/css.php?k=2ed2a0138e7654e46fa439cb89097150&amp;o=i&amp;t=1705903151\" width='1' height='1' /><div class=\"license_block\"><div class=\"wp_license\">\n\n<a rel=\"license\" href=\"http://creativecommons.org/licenses/by-sa/3.0/\"><img src=\"\" alt=\"Attribution-ShareAlike 3.0\"/></a>\n<br />\nThis work  is licensed under a <a rel=\"license\" href=\"http://creativecommons.org/licenses/by-sa/3.0/\">Attribution-ShareAlike 3.0</a>.\n\n</div></div><script type='text/javascript' src='https://blogs.gnome.org/raphael/wp-content/themes/twentyfifteen/js/skip-link-focus-fix.js?ver=20141010'></script>\n<script type='text/javascript'>\n/* <![CDATA[ */\nvar screenReaderText = {\"expand\":\"<span class=\\\"screen-reader-text\\\">expand child menu<\\/span>\",\"", "ordPress</a>\n\t\t</div><!-- .site-info -->\n\t</footer><!-- .site-footer -->\n\n</div><!-- .site -->\n\n<img alt='css.php' src=\"https://blogs.gnome.org/raphael/wp-content/mu-plugins/cookies-for-comments/css.php?k=2ed2a0138e7654e46fa439cb89097150&amp;o=i&amp;t=1705903151\" width='1' height='1' /><div class=\"license_block\"><div class=\"wp_license\">\n\n<a rel=\"license\" href=\"http://creativecommons.org/licenses/by-sa/3.0/\"><img src=\"\" alt=\"Attribution-ShareAlike 3.0\"/></a>\n<br />\nThis work  is licensed under a <a rel=\"license\" href=\"http://creativecommons.org/licenses/by-sa/3.0/\">Attribution-ShareAlike 3.0</a>.\n\n</div></div><script type='text/javascript' src='https://blogs.gnome.org/raphael/wp-content/themes/twentyfifteen/js/skip-link-focus-fix.js?ver=20141010'></script>\n<script type='text/javascript'>\n/* <![CDATA[ */\nvar screenReaderText = {\"expand\":\"<span class=\\\"screen-reader-text\\\">expand child menu<\\/span>\",\"collapse\":\"<span class=\\\"screen-reader-text\\\">collapse child menu<\\/span>\"};\n/* ]]> */\n</script>\n<script type='text/javascript' src='https://blogs.gnome.org/rap"]}