domenica 25 settembre 2011

Do not be afraid of using structs for you (internal) implementations!

With the advent of OOP languages, developers seem to have forgotten that not everything need to be a fully implemented class. In a typical program you have bunch of data that must be collected together, but that not always needs to expose all the OOP features such as encapsulation (i.e., having hidden properties), accessors (i.e., getters and setters) and a polymorphic behaviour. Sometimes you need only to store a few fields together, for internal uses and just for your own convenience. A typical example is when you deal with external resources, for instance something that comes from an underlying software/library. In such cases, it is probably you will not be able to change the data that is passed back to you, but you have only to read and take actions depending on its value. In this scenario, it does not make any sense to build a fully object with a lot of getters/setters/constructors/destructors, a simple struct-like packaging will suffice.
Another example is when you have to deal with a few annotations at the same time; instead of accessing each annotation to get each value, you can pack values into a struct-like object and access such fields directly. Since you are not supposed to change an annotation at run-time, creating setters does not make sense, and therefore creating getters does not make sense either. So just skip them and use a struct!
I know that your OOP-soul is screaming about the above, but trust me, each method you add requires a new stack allocation (if not inlined, of course) and does not provide you with much more control than you require. After all, consider the following simple example (Java code):

class Person{
       private String name;
       private String surname;

       public String getName(){ return name; }
       public void   setName(String n){ name = n; }

       public String getSurname(){ return surname; }
       public void   setSurname(String n){ surnname = n; }

How often have you changed the accessor methods? I guess that for almost the 95% of you beans you don't have to overload the generic logic of getters and setters. In such a scenario, having the following is much simpler to write and to use at run-time:

class Person{
       public String name;
       public String surname;

There is of course a problem: if you need to change your accessing rules, you will not be able without breaking compatibility. In other words, once you expose a struct public property, you will never get it back!
However, as you can see, the class is not public, that in Java it means that it cannot be accessed outside the current package. In other words, the class does not represent a public API, but a private one, and you are always able to change it depending on your wills without even having clients to notice it.

There are also other cases when using struct-like objects is allowed, and an example is when your OOP API is an adaptor of an external API. An example can be found into the SWT Java GUI API, that being a kind of reimplementation of the Operating System API, it make a deep use of structures because they maps really well into the Operating System data structures.

In conclusion, the main idea of this article is that structs are good, but must be used with caution to avoid to make public something that could requires soon or later a different control path. But if you are sure you are using objects for your internal implementation and/or to map other languages/libraries structs, use them without being scared of!

Nessun commento: