2016 m. rugsėjo 21 d., trečiadienis

Socialdemokratų partijos programos TL;DR

Iki šiol tai vienintelė partija iš nagrinėtų, kurios programa nėra akivaizdžiai patalpinta partijos tinklalapyje. Teko truputi pasistengti, kad surasčiau. Tenka konstatuoti, kad radinys tikrai vertas būti slepiamas. Palyginimui: 29 puslapiai prieš konservatorių 280 ir liberalų 180...
Šį kartą didžiąją dalį apžvalgos sudarys tiesiog cituojami programos punktai.

Pozityvas:

  • Didelis dėmesys neįgaliesiems

Negatyvas:

  • 29 puslapiai lozungų (prisimenam Valinsko programą). Panašu, kad kaip dirbo, taip ir programą rašė...
  • Svarbu nepamiršti paminėti, kad dešinieji nuvarė šalį.
  • O jau prižadėta, prižadėta... ir iš kur tiek pinigų? Nes mokesčių tai nelabai ruošiasi keisti.

Švietimas

Atmetus beletristikas, kur nieko naujo, ištraukiau štai ką:
- prie svarbiausių būsimų darbų parašyta: "Aukštojo mokslo bakalauro studijos bus nemokamos."
- bet atskiroje švietimo dalyje: "Priimant studentus į aukštąsias mokyklas bus laikomasi valstybės užsakymo principo. Visi pagal valstybės užsakymą į aukštąsias mokyklas priimti bakalauro studijų studentai mokysis nemokamai."
Tai nemokamos ar daliai vis tik mokamos? O gal tiesiog bus viskas pasiekta nieko nedarant ir paliekant kaip yra, nes ir dabar mokslas "nemokamas"?

Ekonomika:

  • "Pereisime prie atviru kodu paremtų duomenų bazių valdiklių, operacinių sistemų ir ofiso programų paketų."
  • BVP vienam gyventojui pasieks 85% ES vidurkio, vidutinė alga 1100€, minimali 550€, pensijos didės trečdaliu, Išmokos žemdirbiams pasieks ES vidurkį, ... KAIP?
  • Atrado internetą ir startupus. Kaip suprantu iš programos, pati vyriausybė imsis investuoti į startupus?
  • "Minimalus mėnesinis atlyginimas pasieks 50 proc. vidutinio atlyginimo dydį.", nors wikipedia sako, kad jau dabar maždaug taip ir yra...
  • "Bus pertvarkyta valstybinio socialinio draudimo sistema, dėl to išaugs jos tvarumas ir gebėjimas užtikrinti orias ..." - o ką konkrečiai keisite?

Kita:

  • "Veiks jaunimo pirmojo būsto programa" - parašyta prie svarbiausių ekonominių dalykų, daugiau programoje šiuo klausimu nieko...

Keletas citatų iš programos, turėtų nemažai pasakyti (kai kur pabaigoje parašiau komentarą):

  • "Ankstesnis konservatorių ir liberalų valdymas buvo pražūtingas šaliai."
  • "Bus užtikrintas Lietuvos žmonių saugumas." - čia atskiras punktas ekonomikos skiltyje :/
  • "Sutrumpinsime gamybos įmonių planavimo ir statybos ciklą."
  • "Bus plėtojama žiedinė ekonomika ir ekodizainas, užtikrinamas gaminių ilgaamžiškumas, remonto ir gaminių atnaujinimo galimybės, lengvas jų išardymas, perdirbimas į antrines žaliavas."
  • "Padėsime startuoliams tapti globaliomis kompanijomis."
  • "Ir toliau didinsime informacinių technologijų specialistų skaičių."
  • "Veiks nacionalinė elektroninės sveikatos duomenų bazė." -- kas yra elektroninė sveikata manęs neklauskit :D
  • "Trenerių atlyginimai padidės iki 30 proc." -- čia visa atskira pastraipa programoje :/
  • "Įrengsime dūmų filtrus visose miestų katilinėse ir kogeneracinėse jėgainėse." -- čia seimo ar vyriausybės atsakomybė ???
  • "Bus toliau plėtojama ir ilginama maisto gamybos grandinė – nuo ūkio iki stalo, garantuojanti aukščiausią maisto produktų kokybę ir didesnės pridėtinės vertės kūrimą." -- WTF? Maistą branginsit?

2016 m. rugsėjo 20 d., antradienis

TS-LKD programos TL;DR

Privalumai
  • Labai detali esamos situacijos analizė, įvardinto problemos (nors dauguma jų - nieko naujo).
Trūkumai
  • Proza, atrodo daugiau kaip romanas, nei programa.
  • Sunkiai skaitoma ir labai daug (280 psl). Daugumos kitų partijų net neskaityčiau.
  • Nuolatinis varymas ant dabartinės valdžios kiekviename skyriuje.
Ekonomika:
  • Konkrečių veiksmų, įstatymų pakeitimų nerasta
  • Daug kosminių idėjų (pvz. vidutinis atlyginimas 1250€)
  • Kopijuosim Airiją ir būsim kaip Airija...
  • Daugiau Airijos istorijos ir esamos padėties Lietuvoje analizės, nei veiksmų plano
  • Idėjos, net jei ir konkrečios, nėra konkrečių KAIP
  • Didelis dėmesys investicijoms į regionus
Švietimas
  • Daug beletristikos
  • Daug mokytojų padėjėjų, pakaitinių mokytojų ir pan. Už kokius pinigus?
  • Nuo 8-9 klasės privaloma praktika privačiame arba valstybiniame sektoriuje
  • Tradicinė mintis mažinti universitetų, bet nėra jokių konkrečių planų, ką su kuo sujungs
Valstybinio sektoriaus pertvarka
  • Įšaldyti atlyginimų fondą
  • Mažinti valdininkų skaičių, to sąskaita didinti atlyginimus
Kita
  • Atsijungti nuo Rusijos elektros sistemos, sinchronizuoti su vakarų
  • Universali 9 mėn. karinė tarnyba visiems baigusiems vidurinę
  • Daug visur visokio finansavimo didinimo, niekur nepasakyta, iš kur pinigai

2016 m. rugsėjo 19 d., pirmadienis

Liberalų sąjūdžio programa, TL;DR

Programos privalumai: aiškiai stuktūrizuota, išskirti esminiai punktai, aiškios gairės, nėra svaidomasi kaltinimais kam nors
Programos trūkumai: atmetus ekonomikos dalį daugiausia gan abstrakti beletristika („sieksime“, „skatinsime“ ir pan.)
Ekonomika: Mažinti mokesčius, didinti pensijas, subalansuoti valstybės finansus, mažinti valstybės skolą ir atsidėti... tik neaišku KAIP?!!! Vienintelis variantas yra 2,5 mlrd. ištraukimas iš šešėlio, bet, vėl neaišku, KAIP?!!!
Ekonomikos akcentai:
  • Darbo mokesčių normalizavimas: alga ant popieriaus=darbo vietos kaina, visi mokesčiai mokami darbuotojo, pinigine prasme niekas nesikeičia, tiesiog mokesčių pertvarkymas
  • Sodros mokestis bus mažinamas po 1% iki 2020 metų
  • Sodros lubos - 5 draudžiami pajamų dydžiai (2225€)
  • NPD lygus minimaliai algai
  • PVM sumažinti iki 18%
  • Mažinti pelno mokestį
  • Akcizų benzinui ir dujoms mažinimas (nenurodyta kiek)
  • Nepritariamas automobilių ir nekilnojamo turto mokesčių įvedimui
  • Visokie bla bla kurie neva padidins algas iki bent 1000€, pensijas iki 400€, nelabai įtikina...
  • Daug bla bla apie investicijų pritraukimą
  • Siūlo leisti gyventojams daugiau įtakoti mokesčių paskirstymą, panašiai kaip dabar su 2% GPM
Švietimas:
  • Beveik vien abstraktus bla bla bla...
  • Visur visokie krepšeliai
  • Aukštųjų ir profesinių mokyklų jungimas, nedetalizuota. Pvz., neaišku kaip konsoliduoti Šiaulių Universitetą, kai tam pačiam miete nėra prie ko jį prijungti...
Sveikatos apsauga
  • Daug bla bla ką darys, beveik nieko apie „kaip“ ir „už kokius pinigus“
  • Galimybė turėti alternatyvų sveikatos draudimą
Vidaus reikalai:
  • Institucijų konsolidacija, dvigubai daugiau patrulių, didesnės algos... vėl neaišku KAIP?!
  • Daugiau savarankiškumo regionams
Socialinė politika:
  • bla bla bla... KAIP? UŽ KOKIUS PINIGUS?
Kita:
  • Įteisinti dvigubą pilietybę
  • Įteisinti balsavimą internetu

2015 m. gruodžio 27 d., sekmadienis

Sci-Fi nonsenses

One of the most irritating things when watching Sci-Fi is various mistakes related to real technologies. Here's my list of them.
  1. Pew pew pew
  2. You know what I mean: lasers! Well, not only lasers, plenty of other laser-like guns too. With all that progress they have made you certainly would expect soundless guns to exist. Considering that we have such today! Bonus is that many of those large laser-type guns in turrets on space ships also have a quite powerful recoil.
  3. We live in a middle of nowhere
  4. If you watched sci-fi a lot, you should have seen many cases when spaceship suddenly loses it's ability to fly faster than light. What happens next? Well, they just fly to a nearby planet, which is hours or at worst days away. At the same time our own planet is over 4 light-years away from the nearest other star. This means if some ship breaks down in the middle, it's over 2 years away from any help (if it can fly close to light speed that is). So that's why no aliens have visited us yet - we live in the middle of nowhere!
  5. Ships fly like planes
  6. There is a reason why planes fly the way they do: aerodynamics. They are restricted by our atmosphere. Spaceships however fly in vacuum. There is no reason for them not to be able to turn in place. And with all that fancy technology they have it should be possible for them to make 90 degree turn at high speed. Yet they still prefer to fly in an aerodynamic way. Why?
  7. Wars are fought with weakest weapons there are
  8. Many TV show have very powerful weapons available. A single shot can completely disintegrate multiple humans, a single missile can make entire planet uninhabitable and so on. Yet, when things come to interplanetary war, everyone place it nice and safe: weapons just make non-lethal injuries and planetary bombardments make no more damage than World War II bombs. Everyone is so civilized, no intentions of annihilating your foes even when you lose.
  9. Computers are still stuck somewhere in 70s
  10. This one is where sci-fi creators struggle the most to see the future. Besides human-like AI and ability to talk in human voice computers are more often behind the reality. Just think of it: counting smartphones as computers many of us actually have more than one, while spaceships of hundred years later still have a single computer in them. And often a quite a slow one too.
  11. Ships come to halt on engine failure
  12. What happens when ships engine fails? Usually it comes to full stop. And I'm not talking about faster-than-light travel, sublight speed spaceships also often stop on engine failure. At the same time our primitive space ships fly in close proximity of our solar system with their engines off most of the time. In vacuum there is no resistance you know, so you do not lose speed, hence engines are only for reaching it and maneuvering and fighting gravity.
  13. Aliens have no diversity and are sooo predictable
  14. Even in my city of a bit over half million of people I can't predict how someone will react to certain actions. And we look quite different. Dress different. Have different religions. We even have different native languages, though one dominates. While aliens we encounter in sci-fi are all the same, speak one language, have one culture and are very very predictable. How many times have you heard "these guys will act aggressively", "they never withdraw, that's their weakness", etc. Come on!
  15. We're the only species with creativity in extraordinary situations
  16. When something very unusual happens, our friends aliens, despite being significantly more advanced then us, seem to be unable to find any clever solution. They just do the usual, casual, what they are used to and only we, humans, are able to think of something smart, non-traditional to save everyone. How did those aliens manage to develop so much in the first place?
Got anything to add?

2015 m. gegužės 28 d., ketvirtadienis

C++ inheritance explain (part III)

This is the third part in the series. If you haven't, have a look at part I and part II.

This part is limited to a single, but rather complicated inheritance feature in C++.

Virtual inheritance

Now we've come to one of most complicated features - virtual inheritance.

Let's start as usual, with most trivial example:

class Base
{
public:
  int m_base_member;
  void set_base_member(int x)
    {
      m_base_member = x;
    }
};

class Derived : public virtual Base
{
public:
  int m_derived_member;
  void set_derived_member(int x)
    {
      m_derived_member = x;
    }
};
This time I've added implementations to methods, as they do matter now. Base class translates to this (nothing particular here):

struct Base
{
  int m_base_member;
};

void Base_set_base_member(Base *_this, int x)
{
  _this->m_base_member = x;
}
Now let's see the layout for Derived:

struct Derived_SubObject
{
  int m_derived_member;
};
struct Derived : public virtual Base
{
  void *_vtable;
  Base _parent;
  Derived_SubObject _derived_part;
};
One thing is, that Derived class does have a VTable. That could have been guessed. As you can see, I've split Derived class specific members into a separate struct, that I placed directly inside Derived, rather than inlining members. This was done in order to explain the code in set_derived_member() method, which looks like this:

void Derived_set_derived_member(Derived *_this, int x)
{
  Derived_SubObject *_derived_part = _get_sub_object(_this, Derived_part);
  _derived_part->m_derived_member = x;
}
The important part here is that implementation of set_derived_member() make no assumptions about layout of Derived being passed in, with exception for VTable, which is expected to be at the start. The sub-part of Derived can be located anywhere in the object, method always looks it up via VTable. This has two implications:
  1. negative performance impact, as instead of accessing variable via offset in object, a VTable lookup is performed
  2. in case of multiple inheritance, duplication can be avoided for diamond-problem (as shown below)
class Base
{
public:
  int m_base_int;
};

class Derived1 : public virtual Base
{
public:
  int m_derived1_int;
  void foo(int x) { m_base_int = x; }
};

class Derived2 : public virtual Base
{
public:
  bool m_derived2_bool;
  void bar(int y) { m_base_int = y; }
};

class DerivedMultiple : public Derived1, public Derived2
{
public:
  bool m_multiple_bool;
};


/* DerivedMultiple object; */
Derived1 *d1 = &object;
d1->m_base_int = 3;
d1->foo(6);
Derived2 *d2 = &object;
d2->m_base_int = 4;
d2->bar(2);
Base *b = &d2;
b->m_base_int = 0;
The resulting structs and functions are:

struct Base
{
  int m_base_int;
};

struct Derived1_SubObject
{
  int m_derived1_int;
};
struct Derived1
{
  void *_vtable;
  Base _parent;
  Derived1_SubObject _derived1_part;
};

void Derived1_foo(Derived1 *_this, int x)
{
  Base *base = _get_sub_object(_this, Base_part);
  base->m_base_int = x;
}

struct Derived2_SubObject
{
  bool m_derived2_bool;
};
struct Derived2
{
  void *_vtable;
  Base _parent;
  Derived2_SubObject _derived2_part;
};

void Derived2_bar(int y)
{
  Base *base = _get_sub_object(_this, Base_part);
  base->m_base_int = y;
}

struct DerivedMultiple_Subobject
{
  bool m_multiple_bool;
};
struct DerivedMultiple
{
  void *_vtable;
  Base _parent;
  Derived1_SubObject _derived1_part;
  Derived2_SubObject _derived2_part;
  DerivedMultiple_Subobject _derivedmultiple_part;
};
As you see, in the final layout of DerivedMultiple there is only one Base part. The methods Derived1::foo() and Derived2::bar() have identical code, all they require is a VTable at the start of _this. Because DerivedMultiple satisfies this requirement, it can be passed in directly to either of two.
Let's analyze the code part step by step:

/* DerivedMultiple object; */
Derived1 *d1 = &object;
_get_sub_object(d1, Base_part)->m_base_int = 3;   // d1->m_base_int = 3;
Derived1_foo(d1, 6);           // d1->foo(6);
When doing pointer assignment compiler is not required to do anything about pointer, as all that is needed is a VTable at the start. When accessing anything from Base a VTable-lookup is done to obtain a pointer to Base part inside object. foo() call is trivial.
The code where we use Derived2 is pretty much the same:

Derived2 *d2 = &object;
_get_sub_object(d2, Base_part)->m_base_int = 4;    //d2->m_base_int = 4;
Derived2_bar(d2, 2);   //d2->bar(2);
Last, let's cast to Base and use that:
Base *b = _get_sub_object(d2, Base_part);
b->m_base_int = 0;
The base is obtained the same way as inside implementations of foo() and bar(). The important thing to note here is that making Base into a virtual class does not change that, except that pointer to VTable could be reused then.

This draws few conclusions:

  • Virtual inheritance has negative performance impact, because of regular sub-object lookups
  • In case of multiple inheritance and diamond hierarchy, two copies of common base class can be avoided
  • Internal layout of class is unpredictable, compiler can rearrange sub-objects
  • Virtual inheritance may not solve problem with duplicate base class; this can happen, if there is a complex mix of classes, where some classes do not use virtual inheritance, so their layout has to be preserved

2015 m. balandžio 3 d., penktadienis

C++ inheritance explained (Part II)

This is the second part, explaining how inheritance works in C++ under the hood.
If you haven't read the first part, I recommend to have at least a quick look, as it clarifies the approach I'm taking. You can find first part here.
In this part I'll explain probably the most feared feature in C++ - multiple inheritance.

Multiple inheritance with simple base classes

Let's go for simple, but yet famous diamond problem:

class CommonBase
{
public:
  int m_some_int;
  void set_int(int x) { m_some_int = x; }
};
class DerivedOne : public CommonBase
{
public:
  float m_some_float;
  void foo(){}
};
class DerivedTwo : public CommonBase
{
public:
  bool m_some_bool;
  void bar() {}
};
class DerivedMultiple : public DerivedOne, public DerivedTwo
{
public:
  void baz(){}
  void set_int(int x) { DerivedOne::set_int(x); }
};

This one is tricky. Let's list only resulting structs here first:

struct CommonBase
{
  int m_some_int;
};
struct DerivedOne
{
  CommonBase _parent;
  float m_some_float;
};
struct DerivedTwo
{
  CommonBase _parent;
  bool m_some_bool;
};
struct DerivedMultiple
{
  DerivedOne _parent1;
  DerivedTwo _parent2;
};
Pay attention to DerivedMultiple struct. To make it clear, let's expand it's parents inline:

struct DerivedMultiple
{
  /* DerivedOne _parent1; */
  CommonBase _parent1_parent;
  float m_some_float;

  /* DerivedTwo _parent2; */
  CommonBase _parent2_parent;
  bool m_some_bool;
};
As you can see, DerivedMultiple has two copies of CommonBase! Another thing to note is that DerivedTwo does not start at offset 0!
That immediately raises two questions:
  1. Which CommonBase is used, when needed?
  2. How do we call DerivedTwo::bar() on a DerivedMultiple object?
Answers get clear when we translate the calling code:

/* DerivedMultiple object; */
object.foo();
object.baz();
object.bar();

results in:

/* DerivedMultiple object; */
CommonBase_foo(&object);
DerivedMultiple_baz(&object);
DerivedTwo_bar(&object._parent2);  /* <--- PAY ATTENTION */

As you can see, when we call method, that comes from DerivedTwo, we don't pass in pointer to our object as first argument! Instead, we pass in pointer to the subobject part, where the DerivedTwo part is located!
But now we have another question: what if we call foo() from inside bar()? How is CommonBase resolved when we have pointer pointing somewhere inside DerivedMultiple object?

Let's demystify it with this example:

/* DerivedMultiple object; */
DerivedOne *derived1 = &object;
DerivedTwo *derived2 = &object;
derived1->foo();
derived2->foo();

This code translates into the following:

/* DerivedMultiple object; */
DerivedOne *derived1 = &object;
DerivedTwo *derived2 = &object._parent2;
CommonBase_foo(derived1);
CommonBase_foo(derived2);  /* but, THEY LOOK THE SAME? */
OK, so this gives us two puzzles. First, when assigning pointer to DerivedMultiple to a pointer to DerivedTwo, the pointer is automatically shifted to the subobject part! Second, and the most important, THERE IS NOTHING SPECIAL DONE TO RESOLVE CommonBase!
Yes, that right - the two calls will access the different CommonBase subobject inside DerivedMultiple!

Let illustrate it with numbers:

/* DerivedMultiple object; */
object.set_int(5);
DerivedTwo *two = &object;
two->set_int(6);
int five = object.DerivedOne::m_some_int;
int six = object.DerivedTwo::m_some_int;

Calling set_int() on main object and DerivedTwo will set different m_some_int fields.
Now you know, that multiple inheritance is hated for a reason!

Multiple inheritance involving virtual base class

Take this hierarchy:

class SimpleBase
{
public:
  int m_some_int;
};
class VirtualBase
{
public:
  float m_some_float;
  virtual void foo() {}
};
class Derived : public SimpleBase, public VirtualBase
{
};

The resulting structs are:

struct SimpleBase
{
  int m_some_int;
};
struct VirtualBase
{
  void *_vtable;
  float m_some_float;
};
struct Derived
{
  void *_vtable;
  SimpleBase _parent1;
  VirtualBase _parent2;
};

To make it clear, let's expand parents directly inside:

struct Derived
{
  void *_vtable;
  /* SimpleBase _parent1; */
  int m_some_int;

  /* VirtualBase _parent2; */
  void *_parent2_vtable;
  float m_some_float;
};

As you see, the only changes are related to VTable. There are few possible scenarios:

  • if the first base class is polymorphic, it's VTable can be reused (no need to add such field at the beginning)
  • there might be several pointers to VTable inside class (some can be inherited)
  • every pointer to VTable can point to the same or different place (this is entirely up to compiler)

Method overrides in multiple inheritance

Things get further complicated when we override methods in a class with more than one base.
Let's take this example:

class Base
{
public:
  int m_base_int;
};
class SimpleDerived : public Base
{
public:
  int m_simple_derived_int;
};
class VirtualDerived : public Base
{
public:
  int m_virtual_derived_int;
  virtual void set_int(int x) { m_virtual_derived_int = x; }
};
class Multiple : public SimpleDerived, public VirtualDerived
{
public:
  virtual void set_int(int x) override { m_simple_derived_int = x; }
};

You already have the idea, how resulting struct look like, so I won't bother pasting them here. Let's execute this code:

/* Multiple object; */
object.set_int(5);
VirtualDerived *vd = &object;
vd->set_int(8);   /* <--- HOW DOES THIS ONE WORK? */

When translated to C it looks like this:

/* Multiple object; */
_get_method_address(object._vtable, set_int)(&object, 5);   /* no magic here */

VirtualDerived *vd = &object._parent2;   /* this one familliar too */
_get_method_address(vd->_vtable, set_int)(_get_object_address_for_func(vd, set_int), 8);

Looks like I've been lying to you a bit, when explaining how method overrides work :)
What you see here happening is:

  • method address is obtained from VTable as usual
  • because object we have a pointer to can be involved in multiple inheritance, we can not pass pointer to it to a function - what if we have a pointer to some subobject inside, while method expects a pointer to actual object?
  • before pointer is passed to function, it goes through some compiler function, that looks to VTable and returns us a valid address to pass to function (not necessairy to beginning of real object)
  • function is used all the time when object address is passed to a virtual method, because we never know, what types are derived from given class, the tree can have a very complicated mixture of single and multiple inheritance

Hints for safe use of multiple-inheritance

  • try to use only single inheritance and interfaces; in C++ interface would be a class, that has nothing but statics and pure-virtual methods
  • the biggest problems come from classes with fields and non-virtual methods; try to achieve, that non-first base class has none
  • make non-primary base classes as trivial as possible (ideally interfaces), best top level classes (not derived from anything)
  • avoid diamond, use virtual inheritance once noticed
  • be very very careful

Stay tuned for part III, which will have another complicated aspect - virtual inheritance!

2015 m. kovo 26 d., ketvirtadienis

C++ inheritance explained (Part I)

Inheritance in C++ is one of most complex forms of inheritance there is. Understanding, how it works and what hidden features are involved is useful (if not required) to not mess things up.
I'll try to explain it all in detail by examples.
Before we start, there are few things to note:
  • Visibility (both member and inheritance) has no effect, so everything in all examples is public
  • The C++ code will translated to C code to reveal, what is done automatically by compiler
  • The "C++ compiler" is an imaginary one, in attempt to make things simple and clear
  • Namespaces and name mangling are ignored for simplicity (have no impact on inheritance)

The simple inheritance

Let's start with the most trivial example:

class SimpleBase
{
public:
  int m_some_int;
  void foo(int x) {}
};
class SimpleDerived : public SimpleBase
{
public:
  float m_some_float;
  void bar() {}
};

When compiled, compiler turns it into something like this:

struct SimpleBase
{
  int m_some_int;
};
void SimpleBase_foo(SimpleBase *_this, int x) {}
struct SimpleDerived
{
  SimpleBase _parent;
  float m_some_float;
};
void SimpleDerive_bar(SimpleDerived *_this) {}

How it works:

  • top level class becomes a struct with member variables matching those of the class
  • methods become functions, that take a pointer (in C++ it's actually a reference) to a corresponding struct as first argument, with other arguments being that of the original method
  • inheritance places parent struct as first member, it has an offset 0, so derived class can be casted to a base one (this is done automatically by compiler)
  • special methods (like constructor) and overloaded operators are also methods and are turned into similar functions
  • static methods are just functions, in this case class serves simply as a namespace plus has some visibility related features

Simple inheritance with polymorphic base class

Let's change the example so that base class is polymorphic:

class PolyBase
{
public:
  virtual void foo() {}
  void bar() {}
  int m_some_int;
};
class SimpleDerivedFromPoly : public PolyBase
{
  virtual void foo() override {}
  void bar() {}
  float m_some_float;
};

In this case compiler turns base class it into something like this:

struct PolyBase
{
  void *_vtable;
  int m_some_int;
};
void PolyBase_foo(PolyBase *_this) {}
void PolyBase_bar(PolyBase *_this) {}

What we see different from simple inheritance is that there is something called _vtable as first member (compiler is free to place it anywhere, but it is usual to place it as first member).
Another thing that changes significantly is how methods are called. Let's take C++ code:

/* PolyBase object; */
object.bar();
object.foo();

Compiler translates it to something like this:

/* PolyBase object; */
PolyBase_bar(&object);
_get_method_address(object._vtable, foo)(&object);

The difference you see here is:

  • non-virtual method is a simple function call
  • virtual method call involves so called vtable-lookup: address of method foo is found in vtable (somehow, this is up to compiler), the address is a pointer to function that is called.
The derived class is compiled into:

struct SimpleDerivedFromPoly
{
  PolyBase _parent;
  float m_some_float;
};
void SimpleDerivedFromPoly_foo(SimpleDerivedFromPoly *_this) {}
void SimpleDerivedFromPoly_bar(SimpleDerivedFromPoly *_this) {}

Nothing particular here. Let's see how method calls look like:

/* SimpleDerivedFromPoly object */
object.bar();
object.foo();

becomes:

/* SimpleDerivedFromPoly object */
SimpleDerivedFromPoly_bar(&object);
_get_method_address(object._parent._vtable, foo)(&object);

Notes:

  • non-virtual method calls the method from child class
  • virtual method call is no different at all (except that _vtable is inside _parent)
  • the actual value of _vtable is different for an object of every class, that's how the correct method is found

Simple inheritance with polymorphism added in derived class

Unlike in previous example, this time let's have simple base class and polymorphic derived:

class SimpleBase
{
public:
  int m_some_int;
  void foo() {}
};
class PolymorphicDerived : public SimpleBase
{
public:
  bool m_some_bool;
  virtual void bar() {}
};

This results in the following structs:

struct SimpleBase
{
  int m_some_int;
};
struct PolymorphicDerived
{
  void *_vtable;
  SimpleBase _parent;
  bool m_some_bool;
};

As you see, now things get a bit more complicated, because a pointer to VTable is prepended before parent (it could place it after it too, but I'm placing it this way, because it will make it easier to understand multiple inheritance later)! Let's see how it works!

/* PolymorphicDerived object; */
SimpleBase *base = &object;
base->foo();
object.foo();

When traslated to C, it results in the following. I'll split it to explain individual parts.

/* PolymorphicDerived object; */
SimpleBase *base = &object._parent;
SimpleBase_foo(base);

So, as you see, when assigning to base the pointer is automatically shifted by compiler to point to parent! The pointer to base class actually points not to object, but inside it. This enables the simple method call as it would be if had an object of SimpleBase. Calling inherited method from the real object is also different:

SimpleBase_foo(&object._parent);

in this call not the object is passed as parameter, but the subobject of relevant type.

Last thing to note is downcasting:

/* SimpleBase *base; */
PolymorphicDerived *derived = static_cast<PolymorphicDerived*>(base);
Results in something like this:

/* SimpleBase *base; */
PolymorphicDerived *derived = (PolymorphicDerived*) ((void*)base) - sizeof(void*);

The exact opposite must happen, the pointer must be moved back by pointer size, in order to point at the beginning!
This involves the following things behind scenes:

  • Casting PolymorphicDerived* to void* and then to SimpleBase* will result in invalid pointer (not pointing to subobject part)!
  • Comparing PolymorphicDerived* to SimpleBase* using == or != operator will move one of them (either) by pointer size before comparison

End of Part I. Stay tuned for the next part which will involve one of the scary parts in C++: multiple inheritance!

2015 m. sausio 13 d., antradienis

Basic rules of automated software testing

There are a lot of posts about what should or shouldn't be done when writing automated tests for software. Below is my list.

Tests are written for others first, only then for yourself

There are only few cases, where tests are written to check whether the code works. In most cases writing test is not the most efficient way to check. Instead, tests are written primarily to catch regressions when unrelated changes are made. Since it's quite easy to break something you don't know about, tests are written to prevent others to break something they possibly don't even consider.
As such, claims "I don't need tests" are pretty much void if there is more than one developer on the project.

Test that hasn't failed at least once has not been proven to test anything

Should be obvious, but if the test has never been red, how do you know that it actually tests something? Maybe the test is simply always green and will not catch any bug!
Tests are just like any other code, they have to be verified. The simple way to do this is to introduce a bug in the code and run the test, to see if it fails.

When code evolves, test suite should evolve with it

The only case when code changes not necessarily cause test changes is refactoring. In all other cases if code changes, but tests don't, the new features are not covered, so the test suite degrades.
Test suite is relevant only if it is kept in sync with code it tests.

Tests should test the smallest possible feature set

This is easier said than done. Isolating different features from one another can be difficult. Testing features is only one part. Ideally it should be easy to find, what got broken when test fails. If test depends on multiple features at the same time, failure of that test shows, that one of these features is broken, but not always tells which one.
There are two solutions here:
  • Make tests depend only on one feature, so that test failure indicates a problem with that feature
  • Order tests accordingly. If test depends on 3 different features, but 2 of them have been thoroughly tested before, a failure is likely caused by the third
First one of these two options is preferred.

Testing against mocks is inadequate

It is a popular suggestion by unit-tests proponents to mock everything to achieve single feature isolation.
There is a pitfall in doing so: mocks are never a real thing! Testing against mocks only proves that code works with these mocks! There is almost no software in the world, that is 100% compliant with standards they support or even their own documentation (assuming that software has been around for a while). Yet, people for some reason think, that it is possible to keep mocks 100% identical in behavior to the real thing they imitate.
The real implementations evolve over time and mocks have to kept in sync. Sooner or later they diverge. For this reason integration and end-to-end tests are required, in order to make sure the code works with actual real implementations.

Unit testing is inadequate

Should be obvious: end users don't care, whether your tests are green or not. They care, whether software works or not. Unit tests can prove that individual components work, but they say nothing about the behavior, when those components are put together.

It's not important, whether code or test is written first

TDD zealots claim otherwise and they are wrong. While TDD can increase the coverage and quality of tests, it does not guarantee that!
What matters in the end is the quality of the code and the quality of the tests. When both are good, no one cares, in what order they were produced.

Only testing your own code is risky

in part this is another argument against TDD...
One of the reasons for doing code review is that it is hard to spot problems in your own code. The same applies to tests - when else drills your code besides yourself, the chances of catching bugs increases.

Only testing the correct behavior is inadequate

One common mistake made in automated tests is only verifying that code behaves correctly under correct conditions. For complete testing the opposite should also be tested: code should give errors under incorrect conditions.

Do you have any additional rules to add?

2014 m. rugsėjo 8 d., pirmadienis

Bakcward compatibility sins

Maintaining backward compatibility is more of most important values for every software library, tool or system used by other systems via it's API. However, as system evolves, maintaining compatibility gets harder and sometimes it's not possible to improve it in a desired way, because that would mean breaking compatibility. At those points a tough decision has to be made: maintain compatibility or break it.
The list bellow is not complete by any means, but it shows few examples where I doubt that being backward compatible was the right decision. I also add what I think was the right decision and what we can learn from mistakes made.

  1. WinMain [dead parameter in rarely used function]

    In Windows API, the programs entry point is as follows:
    int CALLBACK WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);
    Note the second argument: it is always NULL!
    The idea is, that this argument had a meaning in 16-bit Windows, but that was completely removed in 32-bit Windows. So, this parameter is in effect meaningless and is here just for backwards compatibility. While that seem to make sense at first, consider that Win16 and Win32 are not entirely compatible! Applications had to be migrated from one to another. And application has exactly one WinMain.
    As a consequence, what you see here is short term backward compatibility (Win16 died quite soon after Win32 appeared) at the cost of long term API pollution. All for something as trivial as application entry point (that can be solved via preprocessor macro).

  2. WPARAM ["hungarian compatibility"]

    In Windows the signature for Window Procedure is like this:
    LRESULT WINAPI DefWindowProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam);
    and the parameter in question is wParam, it's datatype to be exact.
    The point here is that "W" stand for "WORD" in both datatype and parameter name. This was true in Win16 (WORD=2 bytes), but not anymore since Win32 (WORD datatype still is 2 bytes, but WPARAM now is 4 bytes).
    There are two issues apparent here:

    • Hungarian notation is a bad idea and one of the reasons is in front of you (if you haven't noticed - parameter name LIES to you)
    • Generic datatypes (like int) are redefined as something else to make it possible to change them later. This was done in this case too, except that the name encoded the original type before and LIES to us now.
  3. Double.parseDouble(null) vs. Integer.parseInt(null) [bug-compatibility]

    In Java:
    Integer.parseInt(null) // throws NumberFormatException
    Double.parseDouble(null) // throws NullPointerException

    This inconsistency originated from old versions of Java and is kept here for backward compatibility. This is documented behavior, so it's "a feature".
    What this actually is, is called bug-compatibility. The funniest part is that both these methods can throw NumberFormatException, so a fix is quite simple and hardly will break badly something. I mean, if you handle exception properly, it will just work, otherwise you probably have a quite buggy system, one more or less doesn't make a difference...
    Most importantly, these two are very old. Double.parseDouble() dates to Java 1.2, no such number on the other, but probably around the same. YOU REALLY REALLY COULD HAVE FIXED THIS BACK THEN! Instead, Sun maintained backward, sorry, bug-compatibility, just to see the bug getting harder to fix later.

  4. Java generics vs. C# generics [focus on past, not on future]

    Both languages fell into idea of object collections just to find out, that they destroyed a lot of type safety for more verbose coding (lose-lose situation, that is). How did they add generics later, without breaking languages backward compatibility?
    Java went the hard way by turning existing non-generic into generic. They faced three issues:

    • both non-generic and generic collections should be available (so that old code still compiles)
    • convertibility between generic and old non-generic variants (mix old and new code)
    • behavior compatibility (non-generic accepts anything, generic is limited)
    It was easy and correct to default to Object for non-generic collections. Problems arised for generic collections that are more specific than Object. Solution was to make generic argument a syntactic sugar, only available at compile time, that is collection is still like it was before, just casting is auto-added by compiler. This was done, because old (existing) collections always accepted anything, so if an exception is introduced for non-compatible type, an existing code would be broken. Non-generic collection was made convertible to any generic collection (whatever the argument is). That in turn added two new issues:
    • what happens is non-generic is converted to a generic with incompatible argument?
    • how type-safety is controlled in new code, when under the hood is the old non-generic collection?
    Java creators went the easy way in both these cases: they accepted ClassCastException for first and completely forbid direct conversion of one generic collection to other (i.e. List<Integer> can't be directly casted to List<Number>).
    What went wrong here? Four issues:
    • a generic collection can be passed to old non-generic code which is free to insert anything, that will only explode in new code!
    • no generic type can still be casted to other one, even if arguments are compatible, you have to work that around via cast through non-generic collection
    • generic only exists at compile time, no runtime type checking exists
    • you can't forbid new stuff to be generic-only, it still can be used without generic arguments, where Object is assumed
    What they could do instead? Make collections aware of their generic argument and throw exception, when incompatible object is inserted. That would accomplish the following:
    • type safety of generic collection - it will simply never contain incompatible objects
    • casting of references would simply work, as the protection is there at runtime
    • passing generic collection to old code would reveal bugs (object of wrong type inserted) or show invalid assumptions about it ("oops, it's not String-only collection")
    Yes, this approach could break old code. But the alternative, that was chosen, made all new code suck. Looking forward, new code will slowly outnumber old and Java as a language will have inferior generics than it could!

    C# took different approach here. It simply added generics as something completely new, not compatible with old in any way. Not ideal, as interoperability between old and new code is troublesome. But looking forward, old code will die out. So IMO it's a better approach, that that of Java

  5. C++ compatibility with C [not quitting in time]

    So, C++ is designed to be compatible with C, that is "a valid C program is a valid C++ program", as they say... Well, not really for several reasons:

    • the compatibility is lost with the first new keyword introduced (*caugh* class *caugh*) - what used to be a valid identifier, now is not
    • C++ has different linkage because of name mangling, which makes it incompatible with C. Worse, now the C libraries are forced to add extern "C" markers under __cplusplus define, to make themselves compatible with C++
    • enums and structs have tag names in C, but these are real type names in C++
    What could they do? Well, actually they did the right thing, just for far too long. If C++ the goal was to completely replace C, it failed to to that. And it's long past the time to become an independent language and throw some old C junk away (well, you can introduce some constructs to access C from C++, we have so many of them, that few more doesn't really matter).
    What breaking ties with C would achieve:
    • string literals can become real std::string objects with their functionality (like concatenation using "+")
    • arrays can be std::array by default (being assignable is the first win)
    • a lot of standard C library could be wrapped by C++ function that would accept C++ types (imagine printf() accepting std::string)
    • forget extern "C", you could just have something like #cinclude for C headers
Lessons that can be learned

  • A compatibility break, that is almost guaranteed to have a very small impact, is worth to do (WinMain)
  • If you redefine some type via typedef, make new type more generic, so you can change it (i.e. "an integer of size, which is at least X")
  • Hungarian notation is a bad idea, full one is ten times so
  • Bugs should be fixed! A fix that breaks some small importance thing will give you few rants from people, who are the ones to ignore (I can't imagine good developer complaining about fixed bug, even if it broke something in his buggy code).
  • New code or file format will gradually outnumber old one by large margin, thus look forwards, not backwards
  • If you fail to maintain full compatibility, use it as opportunity to break for better future
  • The number of "breaks" doesn't matter, what matter is overall pain introduced by compatibility break. So, if you broke something important, making minor things compatible wont help much.
  • Bonus: it's not possible to maintain backward compatibility forever, plan break in advance and don't give false promises.

2014 m. liepos 14 d., pirmadienis

The lost war against duplicate code

From what I've seen so far, duplicate code is impossible to avoid in any large project. There are multiple reasons, how duplicate code is created and while it is typically assumed, that duplicate code is bad, this is not always the case.

Why duplicate code is bad

  • Duplicate bugs - it's obvious: if bug is discovered in code, the same bug exists everywhere the same code is used, thus there are many places to fix, instead of one
  • Hard to maintain - pretty much the same as previous, but more extended. In particular, you not only fix bugs, but also add features, optimizations and other improvements. Worse is that duplicate code diverges, making it harder to spot.

What "justifies" code duplication

  • Easier to maintain - while we claim the opposite, this one has some truth in it. By copying code written by someone else you are free to change it in any way you want. Changing common code is harder and often requires agreement across multiple involved parties. Bust: it looks so, but it makes code base larger, which in turn makes it harder to maintain.
  • More freedom to change - common code has to remain common, that is you can't add your specific features to it. The biggest problem with this is that it's an organizational issue: if code is duplicated to have more freedom to change it, it indicates a problem with management or company culture.
  • Faster to develop - everything, that requires involvement of multiple parties, takes more time to do. Bust: short term gain, you usually lose in the long run (unfortunately short term gains is what many manager only care about).

How duplicate code happens

  • Incompetence - it's sad, but there are a lot of bad developers. Many of the write code via copy-paste, and, as always, abusing copy-paste results in duplicates. This is what is often assumed when talking about duplicate code and yes, that is what we should fight.
  • Forgot to refactor - this is trickier. It's like the first one except that the developer is actually not bad. It's fine to use copy-paste in order to make things work. The problem is that you have to refactor at the end. Not forgetting to that is the hardest part... There is a gray area between this and the first one. Code review might be an answer to this one.
  • Too much trouble - sometimes avoiding code duplication is more trouble than worth. The place for common code might not exist! Create a library just for couple of functions? Don't forget, that this will bring entire maintenance hell for that library. Also there often is such thing as code ownership and shared code is owned by someone else. In short, we avoid code duplication to reduce problems, not to add new ones. When that is not the case, duplicating code can be acceptable.
  • Created naturally - it's not impossible that two developers might actually write almost identical code. In large projects with a lot of people this does happen and might take a while to find, that two guys of completely different teams wrote almost identical helper function.
So, to summarize, next time before blaming someone for incompetence, have a second thought.

2014 m. gegužės 4 d., sekmadienis

Exception handling is mostly a failure

In short: exceptions are good for system and critical errors (like out of memory). The simple and more expected error is, exception is less useful and more trouble.

Error handling is hard. Not doing it properly comes back with mysterious failures, where no one can understand was went wrong. Doing it properly is pain in the ass, mostly because it takes a lot of time to do a boring lot of coding, when stuff already works! Really, most of us probably just code the happy path first, prove it and then go on handling all the possible not so happy cases. This is generally the right thing to do - what's the point of handling the errors when you're not yet sure the solution is right?

Sinking among ifs

That's the general idea for exception handling. A typical example given to students is like this:
if(open_file()) {
  if(read_file()) {
    if(process_data()) {
      show_result();
    }
    else {
      error("Failed to process data");
    }
  }
  else {
    error("Failed to read file");
  }
  close_file();
}
else {
  error("Failed to open file");
}
The lines in bold are "good code". Everything else is there for error handling. It seems very nice to write all "good" function call one after another and move error handling code somewhere else - welcome try-catch!
try {
  open_file();
  read_file();
  process_data();
  show_result();
  close_file();
} catch(Exception e) {
  // determine and error message here
}
Nice, we have separated the happy path from error handling code, now it's easy to understand what code does!
The real life situations are not so nice...

There are different types of errors

  • Disasters: something that generally shouldn't happen, like hard disk crash. Some errors are so rare and so fatal, that it's pointless to try preparing for them.
  • Fatal errors: stuff that renders applications unusable, i.e. losing network connection is fatal for web application.
  • Expected mistakes: user haven't filled required fields? Specified file name contains invalid characters? such types of errors are predictable and applications should be ready for them.
  • Glitches: a string "15 " (trailing space) in 99% of cases is an integer number 15, dammit.
The interesting thing here is that exactly the same error can belong to different group depending on exact situation. Failure while writing to file can mean that primary hard disk has just crashed and in few seconds entire computer will be unusable, or it can just mean that user has unplugged the USB stick. Who said that failure to open file is fatal? No config - assume hard-coded defaults.

Opening file is so difficult

... So, we are opening a configuration file, that is not required to exist...
File *file = fopen(filename, "r");
Nice, NULL means it does not exist, otherwise it's something we can read!
What's the problem, you can write it the opposite way:
FileStream file = null;
if(File.Exists(filename)) {
  file = new FileStream(filename);
}
Does the same thing. Does it? Congratulations, you've just introduced full-moon bug! Files sometimes disappear, you know, get deleted. That can happen at any point in time, for example right between the existence check and opening... Fatal error, crash, or ... well, that file was never required to be there in the first place? So now code becomes:
FileStream file = null;
try {
  file = new FileStream(filename);
}
catch (Exception e) {
  // ignore
}
Wonderful, what used to be one line, now is... progress.

How badly you can blow?

C once again. You call a function and you expect it to return. Is this guaranteed? No! Application might die inside, but we don't care. longjmp() can be called, but we don't care again - unless we made it ourselves.
Let's "upgrade" to C++. What can happen now? Yes, exception can be thrown, and there are types of them! Worse: new types of thrown exception can be added in the future!
It's considered a good practice to only catch exceptions you do care about and let other populate up the call stack. That's fine, but what about the new types of exception that might be added in the future? It looks like someone didn't design for future...

Exception safety

There is an amazing thing about exception safety I still can't explain. C++ is a language that with it's standard library throws something extremely rarely. A topic called "exception safety" is part of it's books. When we come to Java and co., where exceptions are thrown here, there and everywhere, this is somehow forgotten...
obj.foo(x, y);
You can only guess, how foo works with x and y, but there's one thing most seem to assume - all or nothing. If exception is thrown out of foo(), you want the state of obj unchanged! Simple concept, but not so easy to get it right. Throw more exceptions and enjoy more full-moon bugs.

Exception specifications

This is something that pissed me off when I started learning Java. C++ has them too, but they are optional and no one seems to use them (except for standard library). Some even discourage it.
Looking at C#, they have thrown away specifications entirely.
Looking back at Java... ArrayIndexOutOfBoundsException, PersistenceException and multiple others are "unchecked" exceptions so you don't need to write them all over the place. Are the two I mentioned so "unexcpected"?

Conclusions

  • Exception handling works well with critical errors. Less serious the error is, less efficient exception handling is. For simple errors exceptions are more trouble.
  • Exceptions are designed to separate useful code from error handling code. When exception handling mechanisms appear inside of a nested code blocks, it's a first sign of exception misuse.
  • I also haven't mentioned, that exception are also expensive in terms of performance...

2014 m. kovo 31 d., pirmadienis

Darkest corners of C++

It is good to know language you are programming in.

Placement-new array offset

It turns out that on some compilers new[] might allocate an integer before an actual array even when placement-new is used:
void *mem = new char[sizeof(A) * n];
A *arr = new(mem) A[n];
Whether mem and arr will point at the same address depends on compiler and code. On GCC pointers I get the same pointers, but on Microsoft compiler, when A has a destructor, arr is mem + sizeof(int) or similar. While this mismatch might look harmless at first sight, it isn't - your array gets outside of allocated memory at the end!
Solution - cast pointer and manually loop over array creating each object individually via placement-new.

Pointer that changes

class Base {int x; };
class Derived : public Base {virtual void foo() {} };

Derived *d = new Derived;
Base *b = d;
Here b and d will not point to the same address. Comparing and casting them does the right thing, but if you cast them to void*, you'll see they're not equal! This is because Base is non-polymorphic (no virtual methods), while Derived is polymorphic. So, Derived object has a pointer to vtable at the beginning of it, followed by Base sub-object and then by it's own additional members.
Things get more funny when there are many classes in the hierarchy and multiple inheritance is involved.
Solution: well, don't cast pointers to objects into void*.

Return void

This code is valid:
void foo() {}
void bar() { return foo(); }
Useful, when writing templates.

Pure-virtual function with implementation

Pure-virtual function means that derived class must override it in order to create objects of it. But it does not mean that such method can not be implemented in the base class. The code bellow compiles and works:
class A
{
public:
  virtual void foo() = 0;
};

void A::foo() { std::cout << "A::foo called\n"; }

class B : public A
{
public:
  virtual void foo() override
  {
    A::foo();
    std::cout << "B::foo called\n";
  }
};
Note that it did not compile for me using GCC, when I tried to provide implementation for A::foo inline.

Function-try block

This is quite a tricky feature. Function-try block basically looks like this:
void foo()
try {
  throw int();
} catch(...) {
  std::cout << "Exception caught\n";
}
However, in this form there is no particular use for it. It's just a shorter way of wrapping entire function body in a try-catch.
The real use for this feature (which also works differently) is for constructors. First of all, when used for constructor, it does not really catch exception! It catches and rethrows them! The real use for it is to free resources allocated in initializer list:
class A
{
public:
  A(int x) { throw x; }
};

class B
{
  A a;
public:
  B()
    try
    : a(5)
    { } catch(...) {
      std::cout << "Exception in initializer merely-caught\n";
    }
};
In here exception is thrown in an initializer list. There is no way to catch it in a constructor itself. But the initializer list may be long and some initilizer can have resource allocations, like memory allocation. To free such resources, you have to use such function-try block for you constructor and free them in a catch block. Remember, that exceptions are rethrown here.

Bitfields

When defining a struct it is possible to specify variable sizes in bits:
struct Bitfields
{
  int i:16;
  int j:8;
  bool b:1;
  char c:7;
};
The size of this structure is 4 bytes (on my machine at least). Each variable in the struct takes as much bits as specified and can hold appropriate value range.

And, since this is about C++, there are definitly more :)

2014 m. kovo 2 d., sekmadienis

On a quest for good coding standard

All coding standards suck, except mine!

Reasons for coding standard:

  • Readability - the primary goal of coding standard in organization is to make it easier for developers to understand the code. This asks for consistency, meaningful naming, good comments in the code. It has greater impact on newer developers, less familiar with the code base.
  • Code quality - it is an attempt to make it easier to spot bugs in code, as well to make reasoning behind decisions more obvious. It is expect for code to be easy to modify or fix, without introducing new issues.
Common mistakes
  • Rules, not guidelines. Rules must be followed, guidelines are less strict. Having strict rules everyone is required to follow sometimes actually plays against the initial intent for the standard itself: developers can't make code more readable, because they're required to follow the rule.
  • Consider this example:
    string sign_multiplier = x >= 0 ? 1 : -1;
    string sign_multiplier = x>=0 ? 1 : -1;
    Neither is very easy to read and can be written in more readable way. However, given the choice of two I strongly believe second being more readable. But hey, it breaks one of most common rules - spaces around operators!
  • Standard set to stone. Changing standard is not necessarily bad, it depends on what, how and why you change. Developers change, programming languages evolve, so should standard. Otherwise standard might forbid features, that weren't even there, when the standard itself was written.
  • Adopted standard. Standard should be an agreement among developers on how to write code. Just using someones standard can lead to situation when some rule in standard is hated by every developer. It is the same mistake, when standard is created by someone (who quite often doesn't even write code himself) and thrown upon everyone.
  • No or questionable reasoning. Every rule should have a clear reason, it's good for guidelines to have them too. For one thing, it helps to identify out of date items in the standard. It also can give standard some kind of "spirit", so that guidelines are not just followed or broken. Reasoning should avoid questionable arguments. I.e. what is readable for one person can be rubbish for other. If a rule/guideline was introduced by consensus or strong majority, it is good to state that.
  • Trying to solve unrelated problems. Sometimes people try to solve problems like compiler limitation or bug by introducing rule in the standard. It's a bad idea, because bugs get fixed, limitations get weaker, but standards lag behind. Banning language feature because "developers coming from other programming language might not understand it" is an example of trying to solve lack of training/poor hiring problem by coding standard, which has nothing to do with either.
Common poor reasons for rules
  • Makes code more readable. As already mentioned, "readable" is subjective. Some people find CammelCase readable and underscores unreadable. I personally think exactly the opposite. My suggestion is to avoid any claims that something is more readable.
  • Pointing to other standards. Just because many other standards have certain rule, it does not means yours should have it too. And it's completely void argument to claim the rule is good, "because company X uses it" (replace X with Microsoft, Sun, Google, whatever...). Use other standards as a source for ideas, find their reasons behind rules, but don't just blindly adopt them.
  • Claims from long ago. It's XXI century, we have IDEs, syntax highlighting, etc. We don't need to do anything to make keywords like if, while or for more apparent, it's done for us already. Yet so many standards require to put space between if and opening parenthesis, not that I'm against this, but the reason for this is so out of date...
  • Some numbers lie. Less symbols does not mean it's faster to type. Faster means seconds, not keystrokes. I never found CammelCase to be any faster to type compared to underscores.
Does it really matter?

Since I'm proposing guidelines over rules, this is the primary question to be asked for any rule. Does it really matter?
Obviously some things matter, like naming conventions, indentation or how you place braces.
Take for example space between keyword/function name and opening parenthese in C-like languages. Coding standard can require space, forbid it or... does it really matter? Won't you be able to read code with or without that space? Yes, consistency matters, but to what extent?

Strict numbers are almost guaranteed failure

When standard put a strict limit on something and that limit is exact number, there's a MAX+1 or MIN-1 problem:

  • Line of code can not be longer than 80 characters? So 80-char line is perfect, but 81 is evil?
  • Identifier must be at least 3 characters? So variables x and y are terrible names for X and Y coordinates?
So how to put limits? Well, that's actually a good question. I think we should look at the whole thing, not at separate parts. When it comes to size, one thing tends to affect the other:
  • Longer identifiers lead to longer code lines
  • Longer lines lead to more lines (wrapping)
  • More lines lead to larger functions
  • Larger functions lead to more functions (splitting functions into smaller)
  • ... for gods sake, don't put line limit for class!
Now let's go through this list in an opposite direction:
  • Artificially splitting class into few due to large size is more likely to make code harder to understand
  • It's easier to debug a single function than it is to step through several (oops, step over instead of step into)
  • I personally find wrapped lines harder to read. Especially wrapped conditions.
  • Very long identifiers almost never make code easier to understand.
My definitions of too long:
  • Identifier is too long if people "refuse" to type it (copy-paste or code-completion only), it's horribly too long if they can't remember it exactly
  • Line is too long if it requires to read it several times to "get what it does" (what, not why or how)
  • Function is too long, if reading it through at any point of it you lose track over what it does
  • Class can only do too much, it is never too long or too big
Suggestions to make good standard
  • Start from something very abstract everyone agrees on. Code readability and consistency are good candidates. These should be guiding principles for the rest, a "spirit of the standard".
  • Avoid rules, prefer guidelines. It is good to mention, that guidelines are expected to be followed and are deviated from only for a reason (better corresponds to "spirit").
  • When defining rules, seek consensus. No one says it's easy, but you should at least try.
  • Rules shouldn't change. Think twice before turning anything into rule. CammelCase vs. underscores probably requires rule.
  • It is good to note in standard, why rule or guideline is such ("we voted, this was clear winner").
  • Leave standard open for future modification. However, is is good to note, that "current" is a strong argument, so changes require a strong majority. You can also make the standard reviews, between them standard is locked for modification, but I recommend to avoid this.
  • Don't make one standard for all languages. Just don't.
Tips and trade-offs
  • Standard will be liked by everyone only if everyone equals to one! In a group of people some will always be unhappy. It's probably the best when no one is entirely happy.
  • CammelCase seems to be liked by more people. But you can debate a mix. I personally quite like CammelCase for classes, but underscores for methods.
  • Indentation using spaces looks consistently everywhere without any configuration. With tabs it's almost impossible to reach that. Spaces can be enforced - auto-replace each tab to n spaces, you can't do this with spaces. Personal observation: tabs in standard = mix in code base.
  • In large group of people standard will never be followed 100%. Live with that (but still encourage to follow the standard).
  • I don't recommend to use tools to enforce the standard compliance. Warnings in IDE is a bad idea, because they mix with compiler warnings and warnings only work, when there are close to zero of them.

2013 m. gruodžio 17 d., antradienis

Fedora 20: recover stored passwords, in case you lost them

After upgrading to Fedora 20 (I upgraded to RC before the final release), passwords I stored to GNOME Keyring (Keys and Passwords application, also known as Seahorse) were gone. This can also affect some applications, in my case it was Empathy.
The problem is that with this release GNOME Keyring stores passwords in a different place. It used to be:
~/.gnome2/keyrings
now it is
~/.local/share/keyrings

The solution is quite simple:

  • open Keys and Passwords app
  • lock login keyring
  • copy keyring files from the old location to the new
  • relogin

2013 m. lapkričio 30 d., šeštadienis

How to make good API

Good API is a large part of success. Sometimes it's the nearly only factor, why library/solution was chosen. It's not easy to create a good API and there is no single recipe for that, since different cases have different requirements. Everyone who has used many different libraries across several different programming languages should already have a feeling for what is a good API. I'll try to summarize main points here.

  1. Flexible but convenient
  2. Flexibility is something everyone understands, unfortunately convenience quite often forgotten. Some use cases are frequent, others are not. One key to success is to have dedicated API for most common use cases along side the general more flexible API.
    For example, consider a very simple Person class:
    • You need a no-argument constructor to create empty object, that will be filled later
    • You need methods to get/set first and last name
    • You need methods to get/set a list of middle names (because some people have more than one)
    The list above makes a flexible API. Now let's go to the convenience part:
    • A constructor, that takes first and last names as an argument, because that's what most people have
    • A method to set/get middle name, because very little people have more than one
    In some cultures most people have middle name, so if application is specific for such culture, replace two argument constructor with the one with three arguments.
    The point here is not to limit API to the basic all-cases set, but add additional APIs to make shortcuts for common use-cases.
  3. Flexible but not bloated
  4. This one is part of first one, but it's so frequent, that it deserves to be a separate point.
    Most APIs are designed in a "what-if" way, however you have to stop in time, because there are no limits to "what-if". There's no clear recipe here, since it all depends on exact domain. But there are few guidelines:
    • Something that very high impact and/or hasn't changed for a long time is unlikely to change without early warning
      • i.e. IPv6. We're moving in this direction so long, because too many software were "hardcoded" for IPv4. Were they wrong? No, they saved a lot by doing so. Right now you can chose to either support these two or to make your system flexible to support a growing list of different formats. Is the later worth the additional time? It's up to you to decide.
    • Convenience classes and method are only convenient as long as it's clear what they do and what's the difference between any two of them; here are couple of bad examples:
    • String is simple and very flexible data type
  5. Names should be meaningful, guessable, structured, consistent and short
  6. Naming is one the most important things in API. While meaningful is the most emphasized one, it's far from being the only one. Although most of the time programmer reads code, he also writes it, so being able to guess a name improves his productivity quite a lot, especially accompanied with code-completion.
    Structuring API is very important, when API is large. A good example of how not to structure your API is Window API, while GTK+ is an example of good structuring. In short: your API should have something that separates it from the rest of the world (namespace, package, ... or simple prefix). Large API should be divided into submodules etc.
    Another things that make names guessable is consistency. Naming conventions should be consistent across the API, preferably consistent with other APIs in the same field, domain, language etc.
    Finally, names should not be longer than needed. While longer usually means clearer, there's always certain point beyond which length no longer adds clarity. I.e. MAX_INT is perfectly fine name and making it MAXIMUM_INTEGER_VALUE adds no additional value.
  7. Performance oriented, but convenient
  8. Some APIs are not meant to be called often, others should think about performance. However, convenience should be maintained. Windows API is an example of API, that sacrificed convenience for performance. What it lacks is functions to fill various structures with some default values. It's really annoying to set every struct member. At the same time it is bloated in amount of functions, there are often several functions instead of one. I.e. FindFirstFile() and FindNextFile() could easily be just one functions and who really needs ZeroMemory() when you can use much more powerful memset().
  9. Convenient defaults
  10. The less user has to specify explicitly, the better. Most of the time...
    Default values should be intuitive and meaningful. Otherwise it's better to require to explicitly specify the value.
  11. Carefully chose data formats
  12. In short - don't just blindly use XML.
    If you're making Web Service, think which format for data is most appropriate. It might be XML, JSON or anything else. Remember, that someone will have to use it and it's for their sake.
    It's also important for configuration files. Forcing people to write XML by hand is... well don't use XML when something simpler works just fine.
  13. Configurable, but not over-configurable
  14. This one applies to frameworks. Many of them allow user to change the behavior via some setting in configuration. This is good, but there are limits. First of all, it should be clear which configuration is valid and which is not. The more settings there are, the harder it is to list all allowed combination, not to mention that they should work! "Everything is pluggable, extensible and configurable" is never the answer as it will result in huge and buggy mess. No setting is better then a non-working one.
    For complicated cases white-box can be used: instead of super-configurable black box component have a component composed of smaller components - when limits are reached, user can compose his own component reusing parts of original one.
  15. Synchronous vs. Asynchronous
  16. Asynchronous API is good for operation that might take long to complete. Ideally all long taking operations should be asynchronous.
    At the same time, every asynchronous API is only good if it provides synchronous alternatives. Strange? Asynchronous is good for UI as it makes it responsive rather than hanging it. But when you're already on on non-UI thread, you want to perform sequential actions synchronously, rather then messing up with asynchronous continuations. Since you can't predict where which API will be used, it's better to provide both to the user and let him decide, rather than pushing one or another down his throat.
  17. The are non-English speaking people out there
  18. If you have UI, it should be localizable. If you throw exceptions or otherwise report errors, error messages should be somehow localizable too, either provide error codes along messages, or localize messages themselves.
    Finally, if you have no idea about localization, don't implement it without consulting someone who does. A good start is GNU gettext manual, especially the section about plural form, to get some grasp what you're dealing with.
  19. Backward/forward compatibility
  20. Ideally every new version should be backward compatible with all previous ones, but in practice it's almost impossible. The guidelines here are:
    • Design API from beginning to be extended in future. Be especially carefully with boolean arguments (enum is a good replacement). In C using opaque structures is a good way to provide extensibility in the future, avoid reserved members/arguments, because you can end-up with something like this
    • If future features are known or very apparent, prepare API for them in advance (forward compatibility)
    • Avoid breaking backward compatibility of API, but don't add workarounds to API itself, because later you'll have to be backward compatible with those too
    • Prefer big breaks to often ones: no one likes API breaks, but often breaks seems to be hated more; when you break API, use the chance to fix all known shortcomings
    • Be clear about your API stability, so that users know, when to expect breakages; major releases are good candidates for breaks, subreleases should be backward compatible
    • It is also good to have alpha/beta testing, where new APIs are introduced for users to try, but are not yet stable and might change in final release, user feedback is best way to determine shortcomings
    • Be realistic, if your thing will survive long enough, you will, eventually, have to break it's API
  21. Convention over configuration is dangerous
  22. The point is to save developers time. In practice, not in theory! Just because developer writes less code/configuration does not mean he actually spends less time on it.
    When things work auto-magically, they sometimes don't work in the same magic way and finding out why can be very time consuming.
    Besides, changing convention is very painful, as it's less apparent (everything compiles as it did, but it doesn't work as it did, happy debugging).
Bottom line

Great APIs are not designed behind closed door by few system architects. Constructive communication and involvement from many parties from the beginning is the way to understand the problem.

2013 m. spalio 20 d., sekmadienis

Slam them hard

Someone said your language sucks? Slam them back!
  • C/C++/Java
    switch control structure is terrible because of one small issue: fall-through by default. Making break the default behavior and using continue to fall-through would make it perfect. But, not to be...
  • C
    1. Where are the simple data structures like list?
    2. Working with strings?
  • C++
    1. Changed widely used header by accident?
    2. Oops, forgot the copy constructor again?
    3. Great new compiler, now template error messages are only two pages long!
  • C#
    1. Works on every platform as long as it's Windows. Mono? Have you at least tried it?
    2. When invoking delegate, you have to check if it's not null! Why?!
  • Java
    1. Need to return two values from method again?
    2. When compiling Java became faster than C++, then Maven was invented...
    3. Java <=1.4: who needs templates, store plain objects in collections, Java >=1.5: generics!
    4. Java <=1.7: interfaces are absolutely abstract, anything else would be insane! Java 1.7: great news, you can now provide default implementation in the interface!
    5. Terrible slowness on a large scale and you can scale it even further!
  • Python, JavaScript, Perl, Ruby
    1. Mistyped variable again when assigning?
    2. Added extra argument to widely used function?
  • JavaScript
    1. Forgot to write var... in two places...
    2. Object is function and function is object, but you can't call this function, because it's not a function
    3. Fragility of C + the power of C++ + extra ammunition

2013 m. spalio 4 d., penktadienis

9 reasons not to use XML

When I have to write code that deals with XML, at some point I wish it did not exist...

NOTE: I don't say "don't use XML", I say "think twice before doing so", because simple things should be simple (and XML is unlikely to keep them simple).

Reason for writing this: I've been working with Windows 8 tiles for over two weeks, I need to release some steam...

  1. XML is for storing data, not writing code
  2. Yes, this one is dedicated for Spring, Struts, Ant, Maven and co. You can call it "declarative", "configuration" or anything else, I say "it's code". And XML is terrible for writing code: difficult to read, a lot of extra characters to write... Maybe it's easier to parse, but since when do we design language for compiler/interpreter programmers?
    BTW, you can step through the code using debugger...
  3. It's very difficult to manipulate without dedicated library
  4. Libraries exists, more than enough of them. But quite often modifications you have to make are so trivial, that simple text find&replace seems to be the best solution. But you can't do that, because you have to make sure the string you put to XML does not have characters <, >, ", /, &,... Simply to many of them and who can tell them all without looking somewhere? So, no tools like sed or string methods like replace() for you, use fully featured library to change those two attributes...
  5. It's hard to work with even using dedicated library
  6. Marshaling objects to XML or unmarshaling from is fairly easy, full-featured frameworks are available for this. But it gets more interesting, when you only want to change a couple of nodes and XML document is not made by you. Doing full marshaling is not reasonable: a lot of code and bad performance. To add/remove node or set attribute is not as trivial as you'd wish. Simply string find&replace is out of question, while searching for nodes is either fragile or requires quite a lot of checking. Debugging such code is never fun.
    The only simple way I've seen is manipulating dom in JavaScript, but you're not always lucky to use such dynamic language. With C++, C# or Java this is much more messy...
  7. Slow to read, slow to write
  8. Complex syntax make XML parsers slow compared to the ones for other formats. Formats like JSON or YAML are faster in this respect as well as they are more human-readable. Not to mention simple key-file or INI file formats, which are enough way more often, than they are used. And they are easier to parse by hand than it is to read XML using library...
  9. It's only suited for tree-like data
  10. If data is of simpler structure than tree, say, list of records, XML is too complicated for it. Record-Jar format is more suited for this. The same applies for data, that is more complicated than tree, like graph.
  11. Too powerful for most use-cases
  12. What is the difference between child node and attribute, when to use one or another? Do you need entity reference? Do you need schema validation? Do you need XSLT?
    When you look at what you need and answer "no" to almost every advanced feature, why mess with this format at all?
  13. Difficult to embed into program code
  14. Most C-based programming languages use double-quotes for strings, which are also used for attributes in XML. Happy escaping!
  15. But everyone knows it
  16. That's a valid argument. But you can also say that everyone goes to dentist, so it should be something everyone likes... The fact that XML is industry standard does not make it good, it only means that industry chose this format because they though it was better than alternatives at the time. It does not mean that it still is and it does not mean it is good for the problem you are solving ATM.
  17. XML for UI: from nice to ugly
  18. UI is one place where XML has proven to work well. No surprise, UI is tree-like, so XML just fits right here. More - widgets have properties and children, so attributes and child nodes do the right thing. Application supports plugins? Several XMLs can be merged, Firefox is a good example. Web pages are XML (well, almost), etc.
    Now about the ugly part. Do you manipulate raw XML in the code? Tiles in Windows Store Apps require XML for notifications and badges. The first is ugly - you get predefined template and manipulate it using XML manipulation classes to insert necessary attributes. With badges it's much, much worse. They only support numbers and predefined glyphs (identified by string constants!), but to put a badge you have to prepare the full XML document! F*** you very much.
And now the enterprise hell falls onto my head...

2013 m. liepos 5 d., penktadienis

Gnote runs under Wayland!

Something I coded this evening/early night. Now Gnote can be run under Wayland!

Drawbacks?
Global keybindings do not work and Gnote no longer moves windows between workspaces. You can setup global keybindings in Gnome Control Center, there are command line options you can use.
To get entirely old Gnote, pass --with-x11-support option to configure.

2013 m. birželio 19 d., trečiadienis

The dangers of C++ smart pointers

I've spent an entire day debugging a single segfault in Gnote! Luckyly it only occurred "sometimes" when closing application. It was an issue with C++ smart pointer, Glib::RefPtr to be exact. Here are some dangers you might encauter with all types of smart pointers:
  • Mixing smart and simple pointers is never a good idea, SPs only trully work when used entirely everywhere
  • Make sure you know how pointer WORKS, look at it's source code, if required. Assumptions is evel everywhere, but here they can bring the house down (as could have happened in Gnote)

On issue in Gnote
Glib::RefPtr is designed to point to descendants of Glib::Object, but is not limited to them. It requires that object has methods reference() and unreference(), which do reference counting and, if necessairy, delete the object. The problem is, that RefPtr constructor expects object to have a counter of 1 and does not call reference() (probably related to how GTK+ works). However the destructor does call unreference(). So, if you create RefPtr passing an object, that's already referenced by other RefPtr's, objects internal counter is less than actual number of RefPtr pointing to it. As a result when all RefPtr's are destroyed, you might get crash on some later of them with some nice time to chase this bug down :)

2013 m. birželio 9 d., sekmadienis

Programming best practices I disaprove

  • Class imports instead of package imports
In languages where it's applicable, it's usually recommended or even required. It has a point in C++, where less #include's means faster compilation time, however it only makes sense for a large project that takes long to compile.
For languages like Java it makes little sense. Compilation time is the same, all you really get is that you have to put in effort maintaining your imports. While IDE can help you here, it is still and extra click/key press over and over again, it's extra code changes in your VCS and clutter for code reviews. What for? Some bureaucratic claims of nicer code, nothing more.
  • Code-to-interface
This practice requires to define interface and make code depend on it and not on implementing class. Reasons are clear: easy to create second implementation, easier to test (really?), more enforcement on a proper use of class.
The problems occur, when an overuse kicks in. In my view interface is good, when there is more than one implementation of it. In other cases it's just extra piece of code that causes you problems and usually is there for no real reason. Besides, refactoring class to interface and implementation usually is not hard, in fact rather trivial, so why write interface in advance, when you can add it just when the need arises?
  • Banning any language feature
In corporate coding standards you can find various rules like "use of goto is not allowed", "ternary operator is not allowed" etc.
If language has feature that's not deprecated, why someone should not use it? The use must be proper, of course! Even an ugly thing like goto can actually make code more readable and understandable, just you have to use it in right place and in the right way.
  • Setters/getters, no public fields
That's the most Java-way, public fields are generally banned in Java, everyone just codes setters and getters without thinking. It's even enforced by frameworks etc. Each time I see a five year old class with nothing but private fields and public trivial setters and getters for each of them, I wonder why? To write more code? To prepare for change that's unlikely to happen in a lifetime? And if change happens, are you really ready? You haven't declared throws on a setter, so how are going to add potential validation in future? Yes, you can add unchecked exception, but is existing code ready for that?
  • Single return
Some claim that multiple returns make code more complicated. I find it quite the opposite. When function/method has to do some cleanup before exit, then probably using single return makes it simpler, but in other cases it make it more complicated, adds extra if's and nested blocks etc.
  • Separation of concerns as much as possible
The key point here is "as much as possible". Some people take this to extreme, even beyond the line of sanity. It's fine to chop large and complex problems into smaller and simpler ones, but it should not create new problems. When you chop tree into toothpicks, what you get is a crap. Now you put some design patters to put some pieces together, then another patterns to tie those... Eventually you end up with a crap of patterns and start looking for more fancy ways to implement them...
Some things are interdependent, you can't actually separate them, attempt to do this artificially will only cause you more problems.
Some problems are just hard and you can't simplify them by cutting them in peaces.

To end this on a positive note, here are what believe to be universally best practices:

  • Everything you do, do it for a reason
  • If what you did doesn't meet objectives - undo, replace or fix it
  • Throwing junk away is usually the right thing to do, whatever the cost of that junk