48

Antipattern: the verbose constructor

published on 2008|07|31

Constructors are often used to shortcut dependency injection and parameter passing on instantiation. This is a valid practice and often leads to shorter code. Consider the following example (a simple value object, often used to not mess around with floats and to keep currency and amount together):

class Money
{
    protected $_amount;
    protected $_currency;
    protected $_divisor;
    public function __construct(
        $amount = null, $currency = null, $divisor = null)
    {
        if ($amount !== null)
            $this->setAmount($amount);
        if ($current !== null)
            $this->setCurrency($currency);
        if ($divisor !== null)
            $this->setDivisor($divisor);
    }
    ... setter and getter ...
}

Now consider instantiating this object. Instead of creating a new instance of “Money” and calling three setter, everything can be done compactly in the constructor.

bc . $money = new Money(13200, ‘EUR’, 100);

So for the money object this works pretty well. The code is easy to read, but wait, the first argument can be grasped easily, the second too, but the third? It is not too obvious that it is a divisor is passed. An alternative would be changing the constructor to accept an array. This is a replacement for true named arguments, as e.g. Python supports. Solar uses that a lot, as well as the Zend Framework.

$money = new Money(
    array(
        'amount' => 13200,
        'currency' => 'EUR',
        'divisor' => 100
    )
);

Much better readable but does your IDE code completion works? And what happens if you pass “amoµnt”, because your fingers are as clumsy as mine? Exactly, the parameter will be silently ignored.
But look at this:

$money = new Money();
$money->setAmount(13200);
$money->setCurrency('EUR');
$money->setDivisor(100);

It is at least equally short, readable, your IDE works and if you have problems with the dimensions of your keys on your keyboard (they are too small, it has nothing to do with your fingers) you will be warned. But we could even have an even shorter example while maintaining the readability. With fluent interfaces we would get the following:

$money = new Money();
$money->setAmount(13200)->setCurrency('EUR')->setDivisor(100);

Wonderful! If you want, you can add a newline between each object operator and you would have the same amount of lines but less dense code (sad that we don’t have fluent constructors, isn’t it?). Sometimes setters are so elegant.

So until know one thing should be clear: it is not just about easily writing the code, but about the next guy understanding it too. Because you never write code for yourself. Never. But let’s investigate some real live example. I work with a framework that allows me to define really nifty business logic by just sticking together a bunch of fields and every field having a bunch of validators and filters attached.

class User extends Model
{
    protected function _define(Definition $definition)
    {
        $definition->addField(new StringField('username', true, null, true));
    }
    protected function _getStorageClass()
    {
        return 'UserStorage';
    }
}

All the time I write such a definition, I need to look into the code to check the order of the parameters. I can remember the first parameter, but the rest is too similar. To explain it: the second parameter specifies whether the field is required, the third expects a default parameter and the fourth indicates whether the value can be changed after it has been set once. I’ve talked about filters and validators, right?

class User extends Model
{
    protected function _define(Definition $definition)
    {
        $definition->addField(new StringField('username', true, null, true))
            ->addValidator(new UniqueUserValidator())
            ->addFilter(new LowercaseFilter())
            ->addValidator(new RegexValidator('/^[a-z]+$/'));
    }
}

Definition::addField() returns the passed field object to allow adding validators and filters. What works for validators and filters, should work for the rest too, shouldn’t it?

class User extends Model
{
    protected function _define(Definition $definition)
    {
        $definition->addField(new StringField('username'))
            ->setRequired(true)
            ->setReadonly(true);
    }
}

I admit, a bit more code to write, but a huge improvement in readability and therefore in maintainability. Other variants, where setter are not a good solution is to create an expressive factory. We e.g. have a Criteria object that creates and orders Criterion objects internally. Because we don’t have a fluent constructor, we have a static create-method for the Criteria object.

$criteria = Criteria::create('User')->field('id')->equal(1);

The alternative with just utilizing the constructor would be horribly to read and would have limitations regarding the parameter parsing capabilities (except if func_get_args() is used, which is totally the opposite of the paradigm of strict APIs). But back to the constructor only example:

$criteria = new Criteria('User', array('id' => 1));

And how would you express “id not equal 1” with it? So that’s where expressive factories are an alternative.

Constructors, as like any other method, should have as less parameters as possible but as much as needed. Obvious. The constructor should only allow setting vital information for the object (if the object has a name, there is a good chance, that the name is the parameter of the class’ constructor because it is considered vital). And the ease of use depends heavily whether the parameters passed can be intuitively distinguished by looking at there values. As well when the code is written first time as for maintaining it for the rest of your life.

(There are a bunch of other tricks to make parameters more readable, like using class constants as parameters, but this is out of scope of this article).

Tags: , ,

0

Relational data

published on 2007|11|30

I concede that the relational model is the worst form of DBMS except for all those other forms that have been tried from time to time.
Bill Karvin – In Support of the Relational Model

I can’t agree more with that statement. Also I find software like CouchDb really interesting, it will not be the way to go. Beneath modeling, the main advantage of relational models is the flexible question startpoint (in terms of SQL it means the basic information you have beforehand to get the rest of what you need). If you know just a little about tree structure, the start point problem will be self-explaining. Accessing an upper node from a sub node just can’t be implemented as fast as accessing a flat structure and there relations.

4

Preventing cross site scripting by design

published on 2007|10|22

This is more or less a reply to Dynamic global functions in PHP. My main problems with delegating escaping in the template is the fact, that the people who normally work with templates, are frontend developers and designers. Those who do not and should not care about web security. That is a programmers/architects field. Nobody of the frontend developers should have the possibility to create security level artefacts by accident. So, when a value arrives the template, everything should be done. No special escape-calls should be necessary. I will show you how we do escaping and template value sanitizing at Neu.de. But let’s step through all common models in order to explain, why they are bad. I assume you know the basic MVC-terms, I will use here mostlye view and controller action. First of all, the most common approach. Just assigning variables as-is to the view component:

The second – much better approach – is to escape values before accessing them in the template. This is fine as long as you do not use objects in your templates.

If you have complex, nested objects encapsulating complex business rules, you do not want to convert them to an array to make it possible to escape them afterwards because of speed concerns. So if you pass an object with a method which returns fragile user input, your escaping logic is bypassed. See:

The solution is to wrap assign objects in mock objects. You can easily implement a mock object builder using PHP5s reflection features and create a simple proxy which escapes the return values of every call – or – if an object is returned – wrappes this return object in another mock object. And so on and so on:

Once you implemented that, a) your developers must not care about XSS anymore, they just use the framework and b) you can sleep better at night, because it is not likely probable, that your site is vulnarable against XSS. Sometimes you want to allow HTML-code passing to the template. That’s ok, just give the developer a chance to avoid mocking or escaping. If you want to audit your code for XSS security problems, just grep for the method signature.

11

Interaktionszeug

published on 2007|01|12

Also, heute mal zum Mitmachen: was hielten die Leser davon, wenn es hier bald so aussähe?

Update:
Nachdem hier so viel gemeckert wurde, hier eine geänderte Variante mit weniger klassischer Fraktura und anderem Farbenset.

Tags: , ,

0

Migration allenthalben erledigt

published on 2006|03|28

Was Hanno und Stefan schon zu berichten wussten, gibt es nun auch hier zu lesen: Schokokeks.org ist umgezogen.

Read more …
0

22C3: Technological art off the trodden tracks

published on 2005|12|28

Quite fine talk. Régine Débatty (Weblog, read it!) and Jussi Ängeslevä are currently talking about »Technological art off the trodden tracks«. They’re focusing on the use of »bad« techniques, e.g. RFID-tags, CCTVs and so on, for funny and artistic issues. There thesis are to combine hacking and artistical work.
A good idea, as I think (nevertheless I want to abolish arts) to combine different kinds of »hacking«. Use hacking as a term for creative work on and with different techniques. Constructing a gap between hacking and arts is quite synthetic or do you really argue that all the thing the hackers are doing makes sense?

7

New Clearlooks-Theme and Tango-Icons

published on 2005|12|19

To win the verbal pissing contest (german alias: »Schwanzvergleich«), just a nice screenshot with the cairo-based »Clearlooks 2«–Theme and Tango-Icons

0

Lars’ Wahrheiten

published on 2005|12|13

Heute ist »Tag der Lars’schen Wahrheiten«. Sätze die mit »was ich schon immer sage …« beginnen und in diesem Falle enden mit »Linus Torvalds hat einen unübersehbaren Schatten«.
Mehr dazu gibt‘s bei Bernd, der sich gerne in den selbigen stellt und die entsprechenden Hintergrundinformationen bei Golem.

1

Freie Software und Kommunismus

published on 2005|12|13

Ich sag’s doch schon immer, beides wird sich durchsetzen. Was zuerst passiert kann ich nicht sagen aber das dem nu2m-Designer GIMP gefällt ist ja schonmal ein Anfang …

(Page 1 of 1, totaling 9 entries)