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.
No comments:
Post a Comment