søndag den 14. juni 2009

Introducing Static Intent, a Refactoring Pattern

- Refactoring with the intent to create static utility methods.

In many developers' mind, the keyword static has quite a bad reputation. It is in many cases considered poor Object-Oriented design to overuse static, and developers generally go to great lengths to avoid it, and only use it as a last resort in places where it just exactly fit. Take for instance the design pattern Singleton, which can be used to create globally accessible instances. It is generally implemented through lazy instantiation of a static variable and have an equally bad reputation. But in the case of Singleton, I actually tend to agree - that is bad design - almost never implemented as stateless, even though the pattern dictates this, making it inherently hard to test.

But in many other cases, static can easily be utilized without breaking the Object-Oriented mindset (e.i. utility methods and classes). And it is to this context that Static Intent belongs. It can be seen as an extension to the rudimentary Extract Method pattern.

As stated in the title, this is a refactoring pattern, so let us make an example of a method that needs refactoring. The example is pseudo Java.

public class MyFrame
{
  private Button button1;
  private Button button2;
  private Frame myFrame = new Frame();

  public void initFrame()
  {
    button1 = new Button();
    button1.setCaption("button 1");
    button1.setPosition(10, 10);
    button1.setSize(40, 20);

    myFrame.add(button1);

    button2 = new Button();
    button2.setCaption("button 2");
    button2.setPosition(50, 10);
    button2.setSize(40, 20);

    myFrame.add(button2);
  }
}

The first step in the refactoring would be to extract the two button instantiations and create two private methods.

public class MyFrame
{
  private Button button1;
  private Button button2;
  private Frame myFrame = new Frame();

  public void initFrame()
  {
    button1 = createButton1();
    myFrame.add(button1);

    button2 = createButton2();
    myFrame.add(button2);
  }

  private Button createButton1()
  {
    Button button = new Button();
    button.setCaption("button 1");
    button.setPosition(10, 10);
    button.setSize(40, 20);
    return button;
  {

  private Button createButton2()
  {
    Button button = new Button();
    button.setCaption("button 2");
    button.setPosition(50, 10);
    button.setSize(40, 20);
    return button;
  }
}

As the two methods are quite similar, the next logical step would be to create a generic createButton() method. Also, the button sizes seems to be the same, so let us put them up as final/const member fields.

public class MyFrame
{
  private Button button1;
  private Button button2;
  private Frame myFrame = new Frame();
  private final int buttonSizeX = 40;
  private final int buttonSizeY = 20;

  public void initFrame()
  {
    button1 = createButton("button1", 10, 10);
    myFrame.add(button1);

    button2 = createButton("button2", 50, 10);
    myFrame.add(button2);
  }

  private Button createButton(String name, int posX, int posY)
  {
    Button button = new Button();
    button.setCaption(name);
    button.setPosition(posX, posY);
    button.setSize(buttonSizeX, buttonSizeY);
    return button;
  }
}

And that would be it. The refactoring produced a nice and neat generic method and we are done. However, in my mind, we could take it one step further.

What we have made with the createButton() method is a utility method for creating generic buttons. However, it operates on two member variables - the button sizes. So we cannot make it a static utility method. But let us instead try to pass the two variables as parameters to the createButton() method. Now it does not operate on any member fields anymore, so we could actually make it static. The result is below.

public class MyFrame
{
  private Button button1;
  private Button button2;
  private Frame myFrame = new Frame();
  private final int buttonSizeX = 40;
  private final int buttonSizeY = 20;

  public void initFrame()
  {
    button1 = createButton("button1", 10, 10, buttonSizeX, buttonSizeY);
    myFrame.add(button1);

    button2 = createButton("button2", 50, 10, buttonSizeX, buttonSizeY);
    myFrame.add(button2);
  }

  private static Button createButton(String name, int posX, int posY, int sizeX, int sizeY)
  {
    Button button = new Button();
    button.setCaption(name);
    button.setPosition(posX, posY);
    button.setSize(sizeX, sizeY);
    return button;
  }
}

At first it might seem as unnecessary optimization, but I argue that there are many other benefits of refactoring with the intent to make static utility methods.

When utilizing Static Intent, you end up declaring methods as what they are - utilities. It minimizes the number of methods that access and change member fields, making the class easier to debug and less error prone. It is also easier to unit test these methods as they are stateless and fully independent of the state of the class - the state is fully given as parameters.

In reality, making the method static is not that important - it is much more important to make the methods independent of their class. Making them static is just a guiding line to get there and ends up being a "why not?". The optimization of not having to copy the method to every instance of the class is just added bonus.

The only drawback is that such methods cannot be polymorphic. But in my experience such methods created based on refactoring will most likely become private, making the polymorphism superfluous.

So, in the future I will continue to refactor my code with the intent to make static utility methods. And I encourage you to do the same.

fredag den 29. maj 2009

Function Pointer Curiosities in C++

As a small exercise in my spare time I am writing a generic object serializer for C++. Most likely there exist plenty to of serializers for C++ out there. And that's perfectly fine - I am writing my own as a learning experience - to be up to speed with the language. But in this small project I have come across some curiosities that at first glance seemed quite odd, but after some investigations actually made sense - the only odd thing about function pointers is the notation, which can be very confusing.

I have previously written custom serializers for both Java and C#, but those languages provide the concept of Reflection, which makes the job much easier compared to C++. You cannot ask C++ to list all methods or fields on a given class. Not through the standard at least.

But to stay on the topic of function pointers, let me just quickly sketch out my simple solution for this serializer:

  • a static list of function pointers to each getter/setter of each field in each class


So each serializable class will have a list of function pointers to all the getter/setter pairs in that class.

In order to make the serializer as generic as possible, I will have to make any kind of no-parameter getter method and one-parameter setter method available and useable in the serializer. In Java, that would have been easy - you only have the possibility to provide either objects or primitives as parameter or return type of methods. In C++ that matter is somewhat more complicated. You can have objects, primitives, structs and pointers, references or by-value types and on top of that also const qualifiers on various levels. So a function pointer can come in any different shapes and sizes, even though it is only for single value setters and getters. And in the end, it actually turned out to be the const qualifiers that gave me the most trouble.

But let me start out by giving the simplest example of a getter and a setter function pointer with no pointers nor references and no const qualifiers.

I use typedefs to declare my function pointers and have them all defined in a template class with two templated types: one for the serializable class that the function belongs to (necessary when dealing with class member function pointers in C++) and one for the type of the field behind the getter and setter.It is expected that the type of the field is raw, e.g. stripped from pointers and references. Those are covered later.

template<class T_class, typename T_type>
class Property {
protected:
  typedef T_type(T_class::*Pt2Getter)(void);
  typedef void(T_class::*Pt2Setter)(T_type);
public:
  Property(Pt2Getter pGetter, Pt2Setter pSetter);
};

Note: Don't get confused by the use of the keywords class and typename in the template declaration - semantically they are equivalent. I only use them to differentiate between the meaning of the two templated types.

Introducing pointers and references does not really make the function pointer declaration more complicated:

typedef T_type*(T_class::*Pt2GetterPointer)(void);
typedef void(T_class::*Pt2SetterPointer)(T_type*);

and

typedef T_type&(T_class::*Pt2GetterRef)(void);
typedef void(T_class::*Pt2SetterRef)(T_type&);

By adding the above function pointer declaration to the Property class and introducing new constructors to accept the new function pointers, the class can then be instantiated with pointer, reference or by-value types.

My initial thought was that this would be enough to fully capture all function pointer variants for a getter and a setter. I was wrong.

It turns out that C++, understandably enough, differentiate between the various const qualifiers of a methods signature. A method that as parameter takes a const MyClass* is not the same as a method that just takes MyClass*.

Let us start with the const method. A const method cannot change the object in which it is declared. So this actually only makes sense for getters. Setters will always change the object, e.g. give a new value to a given field.

I will give the example using the pointer declaration:

typedef T_type*(T_class::*Pt2ConstGetterPointer)(void) const;

Another const qualifier is the const return type and const pointer/reference parameter, and here we start to get dirty.

typedef const T_type*(T_class::*Pt2GetterConstPointer)(void);
typedef void(T_class::*Pt2SetterConstPointer)(const T_type*);

And on top of that the getter can still be a const method:

typedef const T_type*(T_class::*Pt2ConstGetterConstPointer)(void) const;

But when we try to define a simple const type function pointer, C++ suddenly becomes cranky:

typedef void(T_class::*Pt2Setter)(const T_type);

where C++ claims that this is equivalent to:

typedef void(T_class::*Pt2Setter)(T_type);

Now what is this? It worked fine with pointers and also for references?

To explain this, we will need to start with the declaration of const variables (taken from the C++ FAQ Lite on Const Correctness):

  • const Fred* p means "p points to a Fred that is const" — that is, the Fred object can't be changed via p.

  • Fred* const p means "p is a const pointer to a Fred" — that is, you can change the Fred object via p, but you can't change the pointer p itself.

  • const Fred* const p means "p is a const pointer to a const Fred" — that is, you can't change the pointer p itself, nor can you change the Fred object via p.


And the fact that:

const Fred* p;

is equivalent to:

Fred const* p;

(See also: The C++ 'const' Declaration: Why & How)

But why does that have anything to do with the above example of method equivalence?

Well, it turns out that in C++ the signature of a method includes the const'ness of the parameter type, but not the const'ness of the parameter variable. This means that the following two methods will have the same signature, and are thereby not overloads of each other and could not co-exist in the same class:

void myMethod(int* const i);
void myMethod(int* i);

But the following two methods will have different signatures, and will be overloads of each other:

void myMethod(const int* i);
void myMethod(int* i);

This makes perfect sense when you think about it. When calling myMethod, you would actively choose to provide a const int* or a non-const int* to the method, and C++ will be able to distinguish between the two overloads. C++ however does not distinguish between whether the given pointer is const or not, only that the type is const.

So in the case of

typedef void(T_class::*Pt2Setter)(const T_type);

and

typedef void(T_class::*Pt2Setter)(T_type);

Here const T_type is equivalent to T_type const, where the const qualifier then belongs to the given variable, not the type. And since C++ does not distinguish between const or non-const parameter variables, these two method signatures are equivalent.

To finish the article on a great finale, I here give another valid function pointer declaration:

typedef const T_type* const(T_class::*Pt2Getter)(void) const;

This indicates that C++ distinguishes between the const'ness of the variable pointed to by the returned pointer and the returned pointer itself.

Phew..