Archive for Programming

Say hello to the ModelListModel

Preface: In my new series “Say hello to…”, I regularly present you additions to my Git-based collection of useful helper classes and smaller projects (see its very simple homepage for more information).


Yesterday, you saw me debugging models. Today, you see the result: I’ve implemented a model that lists other models.

The ModelListModel in action

The ModelListModel in action

Perhaps you find this useful for your own application (I’ll use it for fantastic new features in Palapeli’s puzzle library). In an ideal world, I would have implemented a yet more generic model, in which one can “mount” other models at arbitrary positions, but from what I know about model/view programming, this is very hard to do right (i.e., without massive memleaks).

Comments (6) »

Debugging models is hard work

It’s fifteen minutes till midnight and I’m sitting here and analysing pages of boring debug output. What a life. (At least I chose it freely.)

debugging-models

Some of you might read from this that I’m working on model/view stuff currently. I hope to have visible results tomorrow.

Comments (5) »

Say hello to Utils::SelectionDialog

Preface: In my new series “Say hello to…”, I regularly present you additions to my Git-based collection of useful helper classes and smaller projects (see its very simple homepage for more information).


Today, I needed a dialog for Kolf that shows a list view to the user, and lets him select some items from that (plus the “OK/Cancel” buttons which you’re used to from modal dialogs). I had to create a new class, complete with own header and source file, because I needed to declare a new KDialog subclass with a slot.

Incidentally, I’ve already created such dialogs for Palapeli. And much of them. So this is a task that should clearly be simplified. This is how the SelectionDialog class came into life. See the APIDOX in its header for details on how to use it.

Leave a comment »

Say hello to StaticVector!

I present you the second addition to my Git-based collection of smaller code pieces (which now also has a very simple homepage).

This time, I show you a generic container class. There is already a big bunch of container classes in Qt, but I had to make one that fits my needs: the StaticVector.

Its API and purpose is similar to QVector, but it behaves quite differently: A StaticVector does never reallocate or resize its data unless it’s explicity told to do so. Also, any copy of a StaticVector will be read-only, because the data is implicitly shared for performance reasons, but write operations would require the copy to detach from the original data (which is an implicit reallocation, which is forbidden).

The usecase for this is quite simple: In Kolf, we are regularly passing big data arrays to OpenGL and ODE. And passing big arrays to methods from C libraries almost always requires one to pass a base pointer and a size, i.e., two parameters. With such data encapsuled into classes (such as QImage), you might end up with a situation like the following:


void passData(uint* data, int size);

class MyContainer
{
QVector m_payload;
public:
QVector payload() const { return m_data; }
//...
};

MyContainer container;
//...
passData(container.payload().data(), container.payload().size());

This is asking for trouble. The two calls to MyContainer::payload() in the last line create two temporary objects. The latter one is not problematic, because QVector::size() is a const method, but QVector::data() is a non-const method (because the C library wants a modifiable pointer). Calling it causes this temporary QVector instance to detach from the original payload, i.e., allocate new memory and copy the data to there. The C library will remember the pointer to this newly allocated data. After the passData method call, the temporary QVector instances are deleted, which causes the newly allocated data to be deallocated. When the C library tries to access this data later on, we’ll get a SIGSEGV or even uglier things.

That’s where StaticVector comes in. If you substitute QVector with StaticVector in the above example, everything works well, because the temporary StaticVector instances are read-only, but (for this usecase) may return a non-const raw data pointer.

If you ever need to use C libraries which want non-const data pointers, StaticVector might be a good choice for you, because it allows to get this non-const pointer even from const or read-only StaticVector instances, while it minimises misuse of this pointer as much as possible.

Comments (3) »

Say hello to QRangeSelector!

As suggested yesterday, I’ve set up a Git repository for “a broad collection of smaller code pieces which I’ve acquired over the course of my life”. Find it at http://github.com/majewsky/majewsky-misc/, and clone it from git://github.com/majewsky/majewsky-misc.git.

As some first entry, I actually put some stuff I’m currently working on. In line with Andreas Marschke writing about his recent work on a generic video widget, I’m announcing QRangeSelector. This class is similar to a normal slider, but it does not only allow to select a single value, but to select a range of values from some bigger range. (One may also, given some big range, select a small range from it, and select a value within this range.) QRangeSelector also allows for arbitrary contents to be drawn inside its slider area. This screenshot illustrates some usecases which I need in Kolf. (If you do not see the benefit yet, I’ll do a screencast once the QRangeSelector is used in Kolf.)

Testcase for QRangeSelector widget

Testcase for QRangeSelector widget

Note: The white widgets at the top and inbetween the two QRangeSelectors are simple line edits. I needed those to test keyboard focus.

Comments (8) »

Anticipation

In a programmer’s life, one acquires many smaller code pieces which one might want to share. In my case, I have two sources of smaller code:

  1. In my home directory is a huge directory called “code”. Inside this directory is some directory called “misc”, with other 30 smaller programs (most of them tests for some smaller feature, or a calculation program for some university task).
  2. Esp. during my work on Kolf 2, I’ve written many small utility classes which might also be usable in other situations (most prominently the range selector widget which I’m currently working on).

Over the course of the next days, I’ll select some code from these sources, and make it available publicly in a Git repo under the MIT license (a simplified form of the BSD license and a very liberal and easy-to-use license). Stay tuned.

Comments (3) »

Code documentation is really important

One of the things I learned about during my continuing involvement in Kolf is the importance of code documentation. All of you will know user documentation (handbooks, tooltips, …), and developers know about API documentation. But developer documentation is also happening on a more abstract level. It doesn’t help if you understand what single functions do, if you do not get the big picture. How do these classes work together? And which class should I use in the code I’m working on?

These questions were exactly the ones I couldn’t answer when I was looking at the source code of Kolf 1. It might have been that I could get into it with enough time and will (it seems doable), but you see: Missing developer documentation raises the entry barrier.

I was enthusiastic to get proper, extensive documentation in Kolf 2. From the start, every class API has been documented (the obligatory lower level of developer documentation). Unfortunately, the high level documentation was going very slowly until last weekend. When I started to refactor some internals, I set the private goal to not proceed with the refactoring until I documented the last part. Currently, I’m working on documentation for the basements of Kolf, which look like this:

Class layout in Kolf 2 (cut-out)

Class layout in Kolf 2 (cut-out)

I would like to encourage every developer out there to write high-level developer documentation, to be sure that work on his code can continue even if he is not available anymore. Writing documentation is also a good opportunity for reflections on the class layout and the semantics of the classes.

P.S. You might’ve noticed that above graphics uses TeX fonts. It’s actually written in LaTeX (with PGF/TikZ), the sources are in SVN at trunk/playground/games/kolf-ng/doc (view in WebSVN), where the complete documentation is located (see the README for how to compile).

Comments (1) »

Python experiences, or: Why I like C++ more ;-)

So I’ve been coding some Python lately, because this is the language of choice for the “Computational Physics” course I’m attending. As the name says, it is more about physical and numerical problems than about programming, and the instructors chose Python as it’s easy to get into (most Physics students had not coded up to now).

I was quite excited about that, as I have wanted to learn Python for about a year. The fact that the course has its own mailing list where students can ask questions to their fellows (and, of course, the teachers), allowed for some insight on how beginners in programming get into Python.

First off, Python is mostly good for beginners. “print” works on almost everything, and allows you to very easily inspect your program. You can load your work-in-progress code in IPython, and inspect the values of the computations. (I must admit though that I never used this feature, I’m just too used to inserting “print” statements everywhere and re-running the program.)

In the course of the course (pun intended), the only problem that many people ran into was copy-by-reference. When you’re working on some numerical problem, you’re dealing with number arrays most of the time (we were instructed to use NumPy, together with matplotlib for graphical output). And those are, unlike simple numbers, copied by reference. If you say “b = a”, where a is an array, and then modify the contents of b, you’ll also modify a, as b is just another name for a. The solution is “b = 1 * a”. The multiplication operation causes a deep copy of a to be created.

A big mistake which I (as a senior C++ programmer) did often in the first few weeks is the excessive usage of for-loops with numpy arrays. For example, the following two code pieces are equivalent:

a = numpy.ndarray((N, N))
for x in xrange(N):
    for y in xrange(N):
        a[x, y] = x ** 2 + y ** 2
# or
a = numpy.arange(N)[:,newaxis] ** 2 + numpy.arange(N)[newaxis,:] ** 2

On the first look, the first one looks more well-arranged than the second one (given we do not worry about the double parentheses), but the first one is sllllllloooooooowwwww. For N = 2000, the first one needs 4.16 seconds on my system, while the second one is processed in 0.03 seconds. The simple reason that the for-loops in the second codes are hidden deep in Numpy’s implementation, which is done mostly in C (and some Fortran). In an actual example, I had to compare the numerical precision of various discrete integration algorithms. The first version needed 16 seconds to calculate everything and start up, and after transforming all for-loops into Numpy operator expressions, the startup time was reduced to 2 seconds (most of this time was actually spent on loading all modules and initializing matplotlib).

But even this is just a problem of how accustomed you are to an API. I would not say that Python is inferior because it takes ages to execute for-loops in Python itself, rather than in underlying C libraries. Rather, Python is an elegant wrapper on top of many nice libraries, which helps to greatly reduce boilerplate code. Or, as I said to a fellow student, “every scripting language has its use case: Perl has extremely fast string operations, PHP is for website coding, and Python is for extremely rapidly escaping back to C code”.

Today I’ve been working on my final project. (We have to build a bigger application around some numerical or physical problem and present it to the rest of the class.) This has mostly been fun, as this was the first time where I could escape to well-known APIs through the magical key called PyQt4. While I’ve been working on this project, I finally found a way to criticize Python: It’s not optimized on escaping back to C++ code, because the OOP concepts in Python and C++ are, well, completely different things. In C++, classes are blueprints which can be used to create objects. Compare it to civil engineering: Using a construction plan, you put together various materials until the building has emerged.

In Python, a class is essentially a special type of object that works as a function. When this class function is called, it creates a copy of itself and calls the __init__ method of this copy. Here we see that these concepts do not quite fit: It’s like one would just copy the construction plan of a building, lay it out at the building site, connect an air pump to it, inflate it and hope that a building emerges.

There is nothing bad about the class concept in Python in general, the bad thing for me is that it does not match my perspective that I gained to OOP in the last ~10 years. And because it does not match the OOP model in C++, creating bindings seems to be more complicated. For example, I could not create a class that subclasses QObject and QGraphicsItem (a pattern which I regularly used e.g. in Kolf, to get a 2D representation together with signals/slots and properties), and I could not create a Borg-style class that derives from QTimer.

Apart from that, my criticism of Python sums up to missing explicit namespace declaration (why am I bound to file and even directory structure here?) and missing visibility modifiers for class members (“public”, “protected” and “private”) and, most prominently, that duck typing.

The last one is usually destined to be discussed most controversial, so I’ll just neutrally put down my two cents on this topic. If I can choose, I’ll only use strongly typed languages, as in: languages where each variable has a fixed type and unsafe conversions are not allowed, just because it eliminates a very big mass of problem sources. Actually, I would like a programming language which ensures that the most problems do never happen to me (i.e. a strongly typed language with garbage collection, bounds checking and stuff) _and_ runs fast, with very little overhead, and always with the possibility to bypass these checks if the overhead becomes too big. Sadly, I do not know of any language currently in existence that offers me such things.

I do not feel that I’m at a good point to end this blog post, so I’ll just show off some random bling-bling from my Python code at the end: The actual goal of the project is to implement simple pathfinding with genetic algorithms. That means that you start with some random paths, kill bad ones, and mutate and combine the good ones to produce possibly better paths (you know, “survival of the fittest”). I decided to make the thing a bit fancier by allowing obstacles to move around during the calculation, to see how the population reacts on them. This was the perfect moment to try something I’ve wanted to try since a long time: a fluent programming interface. These are programming interfaces where the statements read like sentences:


s = SimulationArea(500, 500)

s.addObject(WallObstacle(400, 0)
    .moveTo(-200, 100).immediately()
    .standStill().forSeconds(2)
    .moveTo(200, 100).forSeconds(5)
)
s.addObject(WallObstacle(400, 0)
    .moveTo(700, 200).immediately()
    .standStill().forSeconds(2)
    .moveTo(300, 200).forSeconds(5)
)

“Hey, wall, move to (700, 200) immediately, wait there for 2 seconds, then move to (300, 300) over 5 seconds.” You get the trick?

If someone’s interested in the full code (once it is finished), I can put it up somewhere (although it will be uninteresting for most of you).

Update: Mh, this blog post got much longer than I intended.

Comments (38) »