Showing posts with label constructor interface. Show all posts
Showing posts with label constructor interface. Show all posts

Wednesday, August 12, 2009

keep logic out of constructors

I'm sometimes tempted to overstuff constructors:


public class AxeMurderer
{
private var _name : String;
private var _crazy : Boolean;

public function AxeMurderer( name : String, crazy : Boolean )
{
_name = name;
_crazy = crazy;

if ( _crazy )
{
for ( var i : int = 0; i < 10000; i++ )
trace( "all work and no play makes Jack a dull boy" );
}
}
}


The overstuffing is the for loop (and possibly the conditional). I clean things up a bit by refactoring to...


public class AxeMurderer
{
private var _name : String;
private var _crazy : Boolean;

public function AxeMurderer( name : String, crazy : Boolean )
{
_name = name;
_crazy = crazy;

if ( _crazy ) writeManifesto();
}

private function writeManfesto() : void
{
for ( var i : int = 0; i < 10000; i++ )
trace( "all work and no play makes Jack a dull boy" );
}
}


But this creates a problem when I write an interface for the class.

Let me pause to say that I try to write my interfaces first, before writing the classes that implement them. That way I'm coding TO an interface. However, in real life that doesn't always happen. Sometimes I can't work out an interface without first writing at least a dummy implementation. In such cases, I go back and write an interface later. At least that I way I have the interface for similar classes.

So, having written the AxeMurderer class, I decide to create an IMurderer interface -- one that has a slightly broader scope than just axe murderers:


public interface IMurderer
{
//Hmmmm....
}


What do I put inside the interface? Looking back at my AxeMurderer class, the only public method is the constructor. That's because I got tempted by a (anti?) pattern: make the constructor build the object by calling a bunch of private methods.

So the interface would be...


public interface IMurderer
{
function AxeMurderer( name : String, crazy : Boolean )
}


But that would force any class that implemented it to have an AxeMurderer method -- terribly inappropriate for a Poisoner or a Strangler!

So, assuming that all types of murders might write a manifesto, I'm going to change my interface to...


public interface IMurderer
{
function writeManifesto() : void;
}


(I'm using a short example to illustrate a point. A real-life IMurderer would insist on methods like Kill(), Spare(), Escape(), Surrender() and BlameItOnJunkFood().)

Now I'll rewrite AxeMurderer as follows:


public class AxeMurderer implements IMurderer
{
private var _name : String;
private var _crazy : Boolean;

public function AxeMurderer( name : String, crazy : Boolean )
{
_name = name;
_crazy = crazy;

if ( _crazy ) writeManifesto();
}

//NOTE: Method now public
public function writeManfesto() : void
{
for ( var i : int = 0; i < 10000; i++ )
trace( "all work and no play makes Jack a dull boy" );
}
}


Note that I'm still calling writeManifesto() in the constructor. That's fine. Some IMurderer classes may choose to automatically write a manifesto; others may choose to only write one if writeManifesto() is called by an external client.

In general, I try to use constructors just for getting necessary external data into the class. Class logic goes elsewhere.