Wednesday, 23 October 2013

Design for errors #2: RAII

RAII stands for Resource Acquisition Is Initialization. This is another simple technique that prevents a lot of errors in code.

Imagine that you have to read some content from a file. You can create code like this:

void readFile(char *fileName)
  FILE *f = fopen(fileName, "r");
  // some code

Note: error handling was removed from all code samples for simplicity.

This looks fairly good on first sight: opened file is closed at the end of function, so no file descriptor is leaked. But what if some code part contains branches and returns early in some of them? In that case explicit fclose() call must be added before each return. Other option is to enforce single exit point policy for whole code. But that is a bad coding practice and can lead to code with unusually large indentations.

RAII idiom helps in such situations. Minimal implementation of RAII for FILE object could look like this:

class FileHandle
  FileHandle(char *fileName) : m_f(fopen(fileName, "r")) {}
  ~FileHandle() { fclose(m_f); }
  FILE * file() const { return m_f; }
  FILE *m_f;

void readFile(char *fileName)
  FileHandle handle(fileName);
  // some code

This is simple class that handles all aspects of FILE initialization and destruction - it opens file in constructor and closes it in destructor. That is everything required to implement RAII idiom. What are the benefits?

Object handle exists only in scope of function readFile  When the scope is leaved (no matter how and where) handle is destroyed. This means that destructor is called and fclose(f) is executed. There is no need to add any code before each return and at the very end of function. Compiler takes care of it. In addition this version is exception safe - object's destruction will take place if an exception is thrown inside some code block.

Another plus of this is that we have to write at least 2x less code for file management - one line instead of two in case of just one exit point. Less code means less possible errors.

Such RAII classes should be used for everything that has state that needs to be restored, like:
Qt lack at least one of such classes. QObject defines blockSignals(bool) method that make a perfect pair (with true and false parameter) for a simple RAII class:

class QObjectSignalBlocker
  QObjectSignalBlocker(QObject *o)
    : m_o(o),
      m_block(o->blockSignals(true)) {}
  ~QObjectSignalBlocker() { m_o->blockSignals(m_block); }
  QObject *m_o;
  bool m_block;

This one block all signals from given QObject and stores previous value of signalsBlocked() status. At the end of scope this value is restored.

Within Kadu we use similar method to block change notifications of our business objects. Each of it has a dedicated ChangeNotifier (.h, .cpp) instance. On each change of property value a notify() method is called on this object and all interested parties are informed by changed() signal. However, if a bulk change is made (several properties are modified at once), there is no need to emit changed() each time. So a pair of block() and unblock() method is provided to enable buffering notifications and merging them into one. Lately I've realized that this is perfect candidate for RAII class, so ChangeNotifierLock (.h, .cpp) was born. It can be set to one of two modes: fire notification or forget all changes that was made during it existence.

Changing code to use it was really simple. We do not have many uses of ChangeNotifier. Also there was no single misuse of this (all block() calls were properly paired with unblock()), but in two cases distance between the calls was bigger than one screen of code. This could lead in future in unfortunate omissions and GUI breakdown (as nothing would get updated anymore). Using RAII class saved us a few lines of code and removed possibility of introducing one kind of error into our code.

From now I'll look for such cases more carefully and implement this idiom where applicable.

Wednesday, 16 October 2013

Kadu translations

In dark ages of Kadu our translations were handled exclusively in source repository (SVN, then git). Some time ago WhE has discovered Transifex site. It makes translating process very user-friendly. Everyone can join and help to make software accessible to more people. Interface is simple yet powerful - it even has suggestions! So now instead of forcing users to send files over e-mail or registering github/gitorious accounts we let them work on their own. All the hard work of updating and merging files is now handled by us.

Switching to Transifex helped Kadu a bit - we now have more translations. Here is list of active ones (percentages are for: whole package, core without plugins, only jabber):
  • English - 100% - 100% - 100% (this is source language)
  • Polish - 100% - 100% - 100% (native language of all current developers)
  • Czech - 95% - 100% - 90% (that is so nice!)
  • Vietnamese - 3% - 10% - 0% (someone just started working on this, we will see how far it will go)
Czech translation will be very probably ready in 100% for 1.0 and next releases.

Unfortunately, most translations are in abandoned state. Some are 2 years old, some were just started and forgotten a while later.
  • French - 64% - 55% - 66%
  • German - 41% - 59% - 60%
  • Russian - 28% - 78% - 0%
  • Italian - 25% - 18% - 39%
  • Spanish - 17% - 33% - 0%
  • Chinese - 11% - 1% - 78%
  • Slovak - 2% - 6% - 0%
  • Turkish - 1% - 0% - 0%
That means we will be able to deliver Kadu will only 3 languages (possibly 4, if Vietnamese gets over 80%). French, German and Russians will have to to be removed (its a shame, because we have shipped these with 0.12.x series).

We would be very happy to release Kadu 1.0 with more translations. So, if you have some spare time, know a language or two, register on Transifex and join Kadu project!

List of strings will not be changed much from now until release (I expect less that 1% of changed and new strings). So you can join and start right now :)

Wednesday, 9 October 2013

Design for errors #1: Immutable classes

There is only one thing in being a programmer that you can be sure of: you will make errors. There is no need for denying it, no matter how good you are, or how good you think you are. Not all mistakes can be detected during code review, unit or integration testing.

My proposition for dealing with this is: design for errors!

What does this mean? Make errors easy to spot and easy to fix. This can be done if you use SOLID principles in development. I would like to add some ideas of my own. Today I will start with first one (loved by functional programmers):

Create immutable classes

Immutable means: does not change after creation. Immutable class in C++ can only set its fields in constructor. No other method is allowed to change state of it (so all methods are declared const). Immutable class should not have any virtual method.

This has one big advantage over normal classes: you are 100% sure that no code is changing created value and you can use it everywhere without worrying about its state.

Look at OAuthParameters class in Kadu source code. It has only one of required properties: it does no have any virtual methods. But it has a lot of setters that change its state. We see in the code that these setters are all used just after object construction, so a Builder pattern should be used for creating instances of this class. There is also a mysterious sign() method. It has very bad property of changing state of this object from unsigned to signed - this state is hidden and not exposed by API in any place. Solution for this would be to make a new class, OAuthSignedParameters that can be created from OAuthParameters by new const method signed() or by some external class.

When all of this is done there will be two separate immutable classes (that are easy to reason about and really error-proof) that have strictly defined relationship. All methods that now require signed version of OAuthParameters will make this clear by requesting OAuthSignedParameters directly. A few types of errors go away with this rather simple change.

That's all for today.

Friday, 4 October 2013

Status update

After changing job (again...) I've found that I have more time and will to code at home ;)
Pace of Kadu development increased significantly and I must announce that OTR is now 100% usable with verification and policy support! (Well, we do not support instance tags as well as in Pidgin, but I don't think it is necessary for first release).

I hope to stabilize it in next week, do some refactoring and renaming in core to adjust for new API requirements and of course add Doxygen comments. After that 1.0-alpha1 will be released and I'll focus on bugfixing others are of application. Kadu has 148 open bugs on redmine, some of them are regressions from 0.12.3. I want to get rid of all regressions and crashes. It would be good to get under 100 again ;)