Page 1 of 1

Coupling by interface or function signature

Posted: Thu Jan 20, 2011 4:27 pm
by VladSun
So, let's say I have two classes -

Code: Select all

class FileList
{
	protected $basePath;
	protected $list;
	
	public function getBasePath() {return $this->basePath;}
	public function get() {return $this->list;}

	...
}

Code: Select all

class Writer
{
	protected $fileList;

	public_construct(FileList $fileList)
	{
		$this->fileList = $fileList->get();
		$this->basePath = $fileList->getBasePath();
	}

	public function write()
	{
		foreach($this->fileList .....
	}
}
or the second class may be:

Code: Select all

class Writer
{
	protected $fileList;
	protected $basePath;

	public_construct(Array $fileList, $basePath)
	{
		$this->fileList = $fileList;
		$this->basePath = $basePath;
	}

	public function write()
	{
		foreach($this->fileList .....
	}
}
or

Code: Select all

class Writer
{
	protected $fileList;
	protected $basePath;

	public_construct(Array $config)
	{
		$this->fileList = $config['fileList'];
		$this->basePath = $config['basePath'];
	}

	public function write()
	{
		foreach($this->fileList .....
	}
}
The last two are "equal" IMHO.

The question is: Which is better -coupling by interface (i.e. first case), or moving it into the function (constructor) signature (i.e. 2nd,3rd case). Or maybe an Adapter pattern?
Second question: Which is better from (Unit)Testing point of view?

EDIT: First example wasn't accurate enough. Fixed.

Re: Coupling by interface or function signature

Posted: Thu Jan 20, 2011 4:40 pm
by John Cartwright
If the classes are closely related, I will always opt to couple them by interface. It allows me to clearly see the relationships between classes and their defined behavior. Some people will obviously argue it is better to keep classes de-coupled, but in instances where they belong to the same package I don't see any advantage (especially in circumstances where we have strict development guidelines).

Now to serve belief that all components should be reusable, when dealing with objects are are NOT closely related, I tend to use preferably a config array of object, simply because I don't want to include a particular unrelated component.

But I'm a mixed bag of peanuts, I'm a supporter of multiple signatures depending on the context. If instances where a wide variety of people will use my code, I will opt for a mixture between #1 and #3, similiar to how Zend supports the injection of a config object.

As far as Unit testing goes, with the latest frameworks it really doesn't make a difference anymore. It is obviously slightly easier to test with the function signature method, simply because we are only opting to pass it data, however, a stub or preferably a mock can easily accomplish the same behavior.

I'm not sure I even answered your question :oops:

Re: Coupling by interface or function signature

Posted: Fri Jan 21, 2011 2:25 am
by josh
VladSun wrote:The question is: Which is better -coupling by interface (i.e. first case), or moving it into the function (constructor) signature (i.e. 2nd,3rd case)
1. You say that as if they are mutually exclusive. Anyways there is no best model, only more useful in some cases at the trade off of being less useful at others. For example having multiple ways to inject a dependency may appease your cognitive dissonance but it comes at the trade off of more code, more to test, and harder to use for newcomers to the code.
Or maybe an Adapter pattern?
2. That's usually used when you don't have control over the code you want to depend on.
Second question: Which is better from (Unit)Testing point of view?
3. Write your tests first and that question becomes meaningless. (see answer #1)

Anyways, to be less technical if all/most methods in a class need a dependency, I put in constructor. If only one method uses a dependency, I inject it as a parameter on the method. If only some methods need it, sprout out a new class & put it on the new class' constructor.

Also sometimes a object may need to hold a dependency, just to inject it into other objects it collaborates with (and may not directly use the dependency). In that case the same logic applies, if there is one method who invokes that code, pass it on that method, if all the methods call some other code that needs the dependency, the constructor is best.

Basically the most important thing is to not grab them out of the global space (singleton), and your code should not run if the dependency isn't injected (exception, syntax error, whatever). If this is true of your code, its probably easier rather than harder to unit test.

Honestly, the main hindrance to unit testing is when I'm forced to stub out seemingly unrelated objects. For example to test that a user can signup, I shouldn't have to worry about stubbing out a Shopping Cart (unrelated to what I'm testing). This creates more verbose test code, which is obviously bad. So the constructor for a user object logically should not have to require a shopping cart. Maybe $user->setShoppingCart() would accept the shopping cart, but certainly not in the constructor since there is things I want to do with a user object, and I may not want to have to have a shopping cart to do those things. For example asking for the user's username should certainly not involve a shopping cart dependency.

Re: Coupling by interface or function signature

Posted: Fri Jan 21, 2011 6:37 am
by VladSun
Thanks, John Cartwright, josh
josh wrote:
Or maybe an Adapter pattern?
2. That's usually used when you don't have control over the code you want to depend on.
I like the idea of using Adapters to adapt interfaces of my own objects in order to have the maximum reusability of each of them.
josh wrote:
Second question: Which is better from (Unit)Testing point of view?
3. Write your tests first and that question becomes meaningless. (see answer #1)
In order to write testsm I should have at least an idea what would be the interface of the object to test, right? I can't imagine how I would write a test otherwise. Building implementation comes after the tests, but defining interface comes before them, right?

Re: Coupling by interface or function signature

Posted: Fri Jan 21, 2011 6:41 am
by VladSun
John Cartwright wrote:I'm a supporter of multiple signatures depending on the context. If instances where a wide variety of people will use my code, I will opt for a mixture between #1 and #3, similiar to how Zend supports the injection of a config object.
Every time I see it, I start to think why PHP doesn't support function overloading, while it supports type hinting :)

Re: Coupling by interface or function signature

Posted: Fri Jan 21, 2011 8:44 am
by John Cartwright
VladSun wrote:
John Cartwright wrote:I'm a supporter of multiple signatures depending on the context. If instances where a wide variety of people will use my code, I will opt for a mixture between #1 and #3, similiar to how Zend supports the injection of a config object.
Every time I see it, I start to think why PHP doesn't support function overloading, while it supports type hinting :)
Believe me.. I think about this everyday.

Re: Coupling by interface or function signature

Posted: Sat Jan 22, 2011 7:38 am
by josh
VladSun wrote:In order to write testsm I should have at least an idea what would be the interface of the object to test, right? I can't imagine how I would write a test otherwise. Building implementation comes after the tests, but defining interface comes before them, right?
Instead of directly constructing the class use a utility method. Now the utility method can be changed in one spot, rather than changing 100 tests for an interface change.

Re: Coupling by interface or function signature

Posted: Sun Jan 23, 2011 7:14 am
by VladSun
josh wrote:
VladSun wrote:In order to write tests I should have at least an idea what would be the interface of the object to test, right? I can't imagine how I would write a test otherwise. Building implementation comes after the tests, but defining interface comes before them, right?
Instead of directly constructing the class use a utility method. Now the utility method can be changed in one spot, rather than changing 100 tests for an interface change.
Huh??? Can you elaborate please? Examples?

Re: Coupling by interface or function signature

Posted: Sun Jan 23, 2011 8:15 pm
by josh
brittle test:

Code: Select all

function testFoo()
{
  $foo = new Foo( true);
  $foo->method();
   $this->assertTrue($foo->state());
}
This test is coupled to the SUT (system under test)'s interface. If we want to replace the boolean with an intent revealing constant, the body of the test method(s) themselves must change. If there's 100 tests that's 100 edits, minimum. Plus how many ever places you have to change it in the production code

solid test:

Code: Select all

function testFoo()
{
  $foo = $this->newFoo(true);
  $foo->method();
   $this->assertTrue($foo->state());
}
This test is coupled to the interface of a test utility method (newFoo). This is a factory method who creates Foo object for us on the fly. I can tidy up the code & change the interface, I only have to edit newFoo's body. This would leave my 100s of tests using a "deprecated" interface where they can be fixed 1 by 1 as I notice the old tests.


Contrast the two,
first example I must change everything at once or nothing at all. This is best for non-volatile interface . The first example creates a very readable test.

second example I can change production code and not have to mirror my changes in test code at the same time. I can put off changing the test code until a later date. This is obviously best for very volatile interface. I sacrifice a little bit of test readability, at the trade off of uncoupling the test from the production code.

Re: Coupling by interface or function signature

Posted: Mon Jan 24, 2011 6:49 am
by VladSun
Yes, that would solve the object creation/initialization problem. But my question (it's not strictly on-topic) was "how to create tests before the object interface (i.e. the set of all public methods) is unknown. Even in you examples you use $object->method(), $object->state which are part of the object interface.

Re: Coupling by interface or function signature

Posted: Mon Jan 24, 2011 7:05 am
by josh
You don't know the set of all methods whether you're writing a test or not..... so your confusion is illogical.

You don't need to know the set of all methods, you just work one method at a time. The same as when you write code normally (without tests).

Even that code example I typed is worked out 1 line at a time. First you figure out what spec you want to implement, that's your test method's name. Then you figure out the command for that behavior, and you write your test using the interface you think is most obvious (same as you would if you were writing it without a test, except you're working from "outside" the method instead of looking at it's declaration). Then at the end you figure out what you want to call the method that you're going to assert on.

I recommend Test Driven Development by Kent Beck (paperback). It'll walk you through the TDD flow in more detail, tutorial style, with code examples and lots of explanations along the way.

Also zend's array style is well suited to TDD, instead of function arguments your class has an associative "options" array, this way you can add & remove parameters without worrying about an inherent order. A good attribute of TDD is the least # of required parameters. You don't want to have to specify 10 parameters when only 1 of them is relevant to a use case.

Also the real answer to your question is you never know the interface ahead of time because these things need to evolve to unpredictable user demand. Test code undergoes constant parallel change to it's production code. When I rename a method I [usually] rename it in production & test code at the same time (and if not its because I've used a wrapper to de-couple test code from production code). In General I'd only recommend the wrapper for object creation (provides a nice place to inject mock dependencies without cluttering the test). Wrapping your actually "business logic" makes the test code have too much indirection.