Home > Principles > Class Constructor Function Should Do No Real Work: Getting Agile Part I

Class Constructor Function Should Do No Real Work: Getting Agile Part I

A while back I read an article by Miško Hevery that was part of a Guide for Writing Testable Code. Granted the stuff that Miško writes about is for the software engineers at Google, and my best guess is that it is primarily for Java programmers. (The examples are in Java and unfortunately [for us ActionScript 3.0 programmers] many of the solutions are through Java libraries.) Nevertheless, we can learn from the larger concepts and apply them to our projects.

Agile, Design Patterns and Unit Testing

If the senior programmers at Google (and I would imagine Adobe, Apple, Microsoft and elsewhere) have a mantra in programming, it’s probably something like this:

Keep it agile!

As most of you know (or suspect), Design Patterns are a type of Agile programming, and the development of both (DPs and Agile) in the 1990′s overlap in content and developers. They were all reading each other’s articles and contributing to one another through venues like OOPSLA and ACM (Association of Computing Machines). The agility movement was in part a reaction to heavy-handed, micro-managed systems of software development processes that were par for the course up to that time. This was not a rebellious overthrow so much as a realization that in order to get things done the processes had to change. In other words, Agile programming and Design Patterns were children of necessity as much as innovation.

The Agile Manifesto

In 2001, a number of developers put forth what they called the Agile Manifesto. It is a concise list of what they have come to value—here it is:

  • Individuals and interactions over processes and tools
  • Working software over comprehensive documentation
  • Customer collaboration over contract negotiation
  • Responding to change over following a plan

The forgers of the Manefesto go on to state that while there is value in the items on the right (normal), we value the items on the left (bold) more.

For those of you expecting something dramatic or revolutionary, you might be disappointed by this tepid manifesto. (These guys aren’t Marx & Engels even though they have PhotoShopped a picture to look like an impressionist painting of anarchists gathered in an ill-lighted London basement as they plan to overthrow the hoary capitalists). Nevertheless, you can see how such a value system is tied into a movement to get out from under the sludge dictated by a focus on protocols rather than results.

No Real Work

As part of unit testing, Miško Hevery argues that the constructor functions should do no real work. By real work, Hevery means,

When your constructor has to instantiate and initialize its collaborators, the result tends to be an inflexible and prematurely coupled design.

For developing design patterns, you can see where this idea is crucial. If each participant (participating class) in a design pattern instantiates/initializes the other participants, you’d get instant lock-jaw. The flexibility and reusability that design patterns afford are lost.

So what should Constructor Functions look like? How on earth can we create agile or any other kind of software if we cannot use collaborating classes through instantiation? The answer to these questions can be seen in good design patterns. The patterns themselves are set up so that you do not make the mistake of having constructor functions, outside of the Client, doing real work. In Part II of this post, we’ll look at some examples. Until then, take a look at some Agile programming to loosen up.

Share

No related posts.

Categories: Principles
  1. January 6, 2010 at 11:41 am | #1

    This article is a total tease… parameterized instantiation has been taught as the best way for classes to work together and to create better systems to unit test against. The only alternative would be to have an init() method to grap collaborating classes… but this just replicates the purpose of the constructor.

  2. John Stone
    January 6, 2010 at 11:54 am | #2

    looking forward to the next article.

  3. January 6, 2010 at 2:23 pm | #3

    Hi Jonathan,

    Parameterized instantiation in the constructor? Other than in the Client, I seldom use parameterized instantiation in the constructor. Maybe you could bring me up to date on this.

    In a more general sense, and maybe this is just me, I try and avoid parameterized elements in all of my class constructors. For example, consider the following. I have a class that makes a ball and leaves up the position of the ball to a calling client. I can do this in one of two ways.

    1. Parameterize the constructor and method
    2. Parameterize the method only

    Here’s the first method:

    ?View Code ACTIONSCRIPT
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    
    package
    {
    	import flash.display.Sprite;
    	import flash.display.Shape;
     
    	public class BallWork extends Sprite
    	{
    		private var shape:Shape=new Shape();
    		private var cushion:Sprite=new Sprite();
     
    		public function BallWork(ex:uint,why:uint)
    		{
    			makeBall(ex,why);
    		}
     
    		public function makeBall(ex:uint,why:uint):void
    		{
    			shape.graphics.beginFill(0xcc0000);
    			shape.graphics.drawEllipse(ex, why, 50, 50);
    			addChild(cushion);
    			cushion.addChild(shape);
    		}
    	}
    }

    In the Client, I make a request by instantiating an instance that includes the x and y position of my object. Unless I want to construct another BallWork object, I’m stuck with the one I have in a fixed position. So, instead, I opt for the following:

    ?View Code ACTIONSCRIPT
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    
    package
    {
    	import flash.display.Sprite;
    	import flash.display.Shape;
     
    	public class BallWork extends Sprite
    	{
    		private var shape:Shape=new Shape();
    		private var cushion:Sprite=new Sprite();
     
    		public function makeBall(ex:uint,why:uint):void
    		{
    			shape.graphics.beginFill(0xcc0000);
    			shape.graphics.drawEllipse(ex, why, 50, 50);
    			addChild(cushion);
    			cushion.addChild(shape);
    		}
    	}
    }

    In the non-parameterized class, I’ve removed the constructor function altogether and just use the method I want. Then, when I make a request; I can instantiate a single object and make all of the individual images I want.

    ?View Code ACTIONSCRIPT
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    
    package
    {
    	import flash.display.Sprite;
     
    	public class Client extends Sprite
    	{
    		//The following line is required for a parameterized constructor
                   //private var ball:BallWork=new BallWork(250,200);
     
    		private var ball:BallWork=new BallWork();
     
    		public function Client()
    		{
    			ball.makeBall(250,200);
    			ball.makeBall(100,100);
    			ball.makeBall(200,90);
    			addChild(ball);
    		}
    	}
    }

    Anyway, that’s what I was talking about. However, I believe you’re referring to something entirely different. In the Proxy example, I used a parameterized constructor function for the ProxyLogin class. That was done because the reference to the Proxy passed a reference to the “Real” object. However, usually I don’t do that because I believe it reduces flexibility.

    Let’s hear from you.

    Kindest regards,
    Bill

  4. January 6, 2010 at 3:02 pm | #4

    Bill, I disagree with the correlation between Agile, Design Patterns and Unit Testing within this article; I also disagree with the interpretation of Misko’s article, ‘parametrized classes’ and what ‘Working software over comprehensive documentation’ means.

    Misko was describing about how Dependency Injection and Inversion of Control enable more testable code – Agile is only peripheral to that point. There are various ways to use DI, constructors with their dependencies parametrized is just one technique – this technique is preferred as it is self-documenting.

    The interpretation of ‘Working software over comprehensive documentation.’ is off. Agile promotes writing (specification) documentation during development; not really about commenting your code. In fact XP’ers promote NOT writing comments. If the code is written correctly, it will be self-documenting – hence no comments.

    The Adapter pattern is not applicable here, rather if any pattern should be mentioned, it’s the Factory pattern. Misko frequently refers to this pattern within his talks. Factories are great for DI and Unit testing, as Object instantiation is abstracted from where it is implementation and a client object will only be aware of it’s dependencies’ signature. This is how Mock objects can be used within Unit Testing

    I think you’re all over the map on this one.

  5. January 7, 2010 at 4:31 am | #5

    Hi Alan,

    Every now and again I go off the reservation, and so I dialed back the post.(See revisions.) Your points about parametrized classes and comprehensive documentation are especially good, and Jonathan made a similar point about parametrized classes. (I go all agro about parametrized classes, and I’d probably be well served if I calmed down about them.) The Adapter example is one for a general point and available example, and it was used in relationship to parametrized classes, which I probably should shut up about for now and focus on Miško’s points. All over the map indeed!

    What’s going to take me a while to nail down is the right kind of example to show Miško’s use of mock objects and an alternative to Guice. As you note, Dependency Injection is one approach, and I’ll probably take that. If you’ve got some ideas how doing this using ActionScript without using @Inject or Guice, I’d like to hear from you.

    Kindest regards,
    Bill

  6. January 7, 2010 at 8:52 am | #6

    Ah, Bill, the example in your comment makes sense- to defer data to a class until its needed instead of passing as much start-up data to the constructor.

    I might be still young in DI, but I haven’t seen a real case benefit for Guice or any other related framework. I still see the same dependency chain… the DI framework class binds the interface to the implementation. A templated factory seems like it can accomplish the same task with almost the same amount of code.

  7. January 7, 2010 at 4:06 pm | #7

    Even more agile for the makeBall example, put special default values in the constructor (like -1), and only have the contructor call makeBall if those default values are not present. That way you can create an empty or waiting instatiation of Ball, and instantiate it when ready, say, after some event has fired like ADDED_TO_STAGE or COMPLETE for the loading of an asset.

  8. January 8, 2010 at 3:48 am | #8

    Hi Scarybug,

    Could you provide an example of what you have in mind?

    This is what I’m seeing now:

    ?View Code ACTIONSCRIPT
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    
    package
    {
    	import flash.display.Sprite;
    	import flash.display.Shape;
     
    	public class ScaryBall
    	{
    		private var shape:Shape=new Shape  ;
    		private var cushion:Sprite=new Sprite  ;
     
    		private var trig:int=-1;
    		private var ex:uint=50;
    		private var why:uint=50;
     
    		public function ScaryBall(trig:int)
    		{
    			this.trig=trig;
    			if (trig!=-1)
    			{
    				makeBall(ex,why);
    			}
    		}
     
    		public function makeBall(ex:uint,why:uint):void
    		{
    			shape.graphics.beginFill(0x00cc00);
    			shape.graphics.drawEllipse(ex,why,75,75);
    			addChild(cushion);
    			cushion.addChild(shape);
    		}
    	}
    }

    Wouldn’t that require a re-instatition of the ball because it is triggered by a state in the constructor? Why not just create the object and then wait until the desired state to fire a desired method?

    Anyway, I may have missed your point; and if so, let me know. A small working example explains a lot!

    Kindest regards,
    Bill

  9. January 10, 2010 at 1:57 pm | #9

    I mean:

    ?View Code ACTIONSCRIPT
    1
    2
    3
    4
    5
    6
    7
    
    public function ScaryBall(ex:Number=-1,why:Number=-1)
    {
    	if (! ex==why==-1)
    	{
    		makeBall(ex,why);
    	}
    }

    that way you can initialize in the constructor if you want to, but by default you won’t.

  10. January 11, 2010 at 3:40 am | #10

    Hi Scarybug,

    Thanks for taking the time to provide that. I put it into working code to test it with the following–two files:

    ?View Code ACTIONSCRIPT
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    
    //Client.as
    package
    {
    	import flash.display.Sprite;
     
    	public class Client extends Sprite
    	{
    		private var ball:Sprite=new ScaryBall(150,100);
     
    		public function Client()
    		{
    			addChild(ball);
    		}
    	}
    }
     
    //ScaryBall.as
    package
    {
    	import flash.display.Sprite;
    	import flash.display.Shape;
     
    	public class ScaryBall extends Sprite
    	{
    		private var shape:Shape=new Shape  ;
    		private var cushion:Sprite=new Sprite  ;
     
    		public function ScaryBall(ex:Number = -1, why:Number = -1)
    		{
    			if (!(ex==why==-1))
    			{
    				makeBall(ex,why);
    			}
    		}
     
    		public function makeBall(ex:uint,why:uint):void
    		{
    			shape.graphics.beginFill(0x0000cc);
    			shape.graphics.drawEllipse(ex,why,75,75);
    			addChild(cushion);
    			cushion.addChild(shape);
    		}
    	}
    }

    Everything works fine, and I was able type it to the interface (Sprite), which adds looseness. My question is this: Why? What would be a use case where you would want to instantiate it with a set of parameters and not use the object?

    If you have the constructor do nothing (take it out as a previous example did); then you can instantiate an object and make as many instances as you want using the method. Because the operation within the constructor function is not fired does not mean that the object is not instantiated. With a parameter in the constructor, you’re stuck with that instance.

    Anyway, I think you’ve added an interesting wrinkle to this thread and I’d like to hear more from you.

    Kindest regards,
    Bill

  11. January 18, 2010 at 11:56 am | #11

    Hey guys,

    nice discussion! It is going all the way from Agile, Dependency Injection, example codes and so on! That’s a good example of good blog post ;)

    My 2 cents for the discussion:
    I might be extrapolating the utilization here but it would be a nice idea if you don’t want to specify the arguments for multiple objects with same parameters. That means, instead of calling multiple times makeBall(100,200), you could just do something like:

    ?View Code ACTIONSCRIPT
    1
    2
    3
    4
    
    var scary:ScaryBall = new ScaryBall(100,200);
    scary.makeBall();          // use the class attribute
    scary.makeBall(333, 444);  // use the provided values
    addChild(scary);

    Them I found this interesting link: http://blog.zarate.tv/2008/10/09/int-and-uint-default-values-are-not-null/

    What helps me deal with constructor with parameters is just the data model good sense. For example: Can a Person.as exist/work without a Heart.as? If no, ENSURE it by passing in the constructor (and test for null if so). Don’t let this open for a setter. Some developers may do something with the heartless person (before the setter).

    ?View Code ACTIONSCRIPT
    1
    2
    3
    4
    5
    6
    7
    8
    
    // this for sure got a heart!
    var Person person = new Person( new Heart() );
     
    // this guy dont neet a heart to do anything (if it make sense)
    var Zombie zombie = new Zombie();
     
    // Heart 'transplant'?
    zombie.heart = zombie.ripHeart( person );

    =)

    ps: I don’t know how to format code here in the comments. =P

  1. January 6, 2010 at 1:04 pm | #1

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>