Page 2 of 15

Re: TDD workshop. Anybody welcome; Data storage abstraction.

Posted: Mon Apr 21, 2008 12:18 pm
by Christopher
Chris Corbyn wrote:Why shouldn't the implementing classes handle that? How does the base class know what the child class is doing, what errors it will throw? Why would it care? :) You can still call set_error_handler() from within the enclosing class.
I don't think it was the issue of the base classes knowing what the child classes were doing. The reality is that the main error that occurs here is when trying to open the file. Once the file is open, the error checking is more specific. That's the common functionality. ;)
Chris Corbyn wrote:It may be the case that at some point down the line we do see common functionality and extract a superclass as part of a refactoring. But that's something that comes from refactoring which we'll get to later. We just want the simplest workable solution possible, and right now we don't seem to need a base class :)
I think that is exactly what Jcart ended up doing. But you need to start simple for this demonstration. Hopfully you come up with a brilliant solution. :)

Re: TDD workshop. Anybody welcome; Data storage abstraction.

Posted: Mon Apr 21, 2008 12:29 pm
by arjan.top
Chris Corbyn wrote:Ok, so our interface for the StorageBridge (name sound ok?) is starting to look like this:

Code: Select all

/**
 * A means of reading/writing data to a storage backend.
 */
interface StorageBridge {
  /**
   * Store a value using $key to reference it.
   * @param string $key
   * @param string $value
   */
  public function set($key, $value);
  
  /**
   * Persist changes.
   */
  public function save();
}
"StorageBackend" sounds better actually. Implementing it as XmlBackend, YamlBackend etc.

soooo why is set() in StorageBridge?

Shouldn't be the bridge responsible only for file read/write?

EDIT:
OK we use name StorageModel from now on as decided ...

Re: TDD workshop. Anybody welcome; Data storage abstraction.

Posted: Mon Apr 21, 2008 12:38 pm
by matthijs
Ok, so we start with something like this

Code: Select all

 
   $store = new DataStore(new XmlModel("/path/to/file.xml"));
   $store->set("/a/know/key", "my value");
   $store->save();
 
But then I don't understand the interface you give. Is that the interface for DataStore or for XmlModel? What are we going to test first. the DataStore or the XMLModel?

Re: TDD workshop. Anybody welcome; Data storage abstraction.

Posted: Mon Apr 21, 2008 1:04 pm
by arjan.top
I would start with StorageModel, then when we have final interface we use mocks on DataStore

Re: TDD workshop. Anybody welcome; Data storage abstraction.

Posted: Mon Apr 21, 2008 4:30 pm
by Chris Corbyn
arborint wrote:
Chris Corbyn wrote:Why shouldn't the implementing classes handle that? How does the base class know what the child class is doing, what errors it will throw? Why would it care? :) You can still call set_error_handler() from within the enclosing class.
I don't think it was the issue of the base classes knowing what the child classes were doing. The reality is that the main error that occurs here is when trying to open the file. Once the file is open, the error checking is more specific. That's the common functionality. ;)
But the implementing class can still handle that error provide it's the one opening the file. What if you had a DB config which is all one with SQL to a "config" table or something? Does the base class still expect errors from the file system? I think I'm missing something in your example :) Can you post a longer use case? Actually, not here... I'll run along to the skeleton forum later ;)

Re: TDD workshop. Anybody welcome; Data storage abstraction.

Posted: Mon Apr 21, 2008 4:54 pm
by Chris Corbyn
arjan.top wrote:I would start with StorageModel, then when we have final interface we use mocks on DataStore
Yeah, so there's no right/wrong way to go about this. We can use mocks before we ever write each model, or we can write the models first. I agree that we might as well jump into writing one of the Models first. I'd say to start with XML for no other reason than "it's as good a place as any".

It's fairly obvious we need to throw in our get() counterpart to set(). Then we can start testing :)

EDIT | Did those who are taking part up until now download the ZIP from earlier? Are we happy with it?

Re: TDD workshop. Anybody welcome; Data storage abstraction.

Posted: Mon Apr 21, 2008 4:59 pm
by Chris Corbyn
matthijs wrote:Ok, so we start with something like this

Code: Select all

 
   $store = new DataStore(new XmlModel("/path/to/file.xml"));
   $store->set("/a/know/key", "my value");
   $store->save();
 
But then I don't understand the interface you give. Is that the interface for DataStore or for XmlModel? What are we going to test first. the DataStore or the XMLModel?
Currently it's looking like both have the same public interface, but the XmlModel acts as an adaptor for DataStore. So any clients only need know about DataStore. We may drop this since we have an interface which represents both... Not sure yet.

Re: TDD workshop. Anybody welcome; Data storage abstraction.

Posted: Mon Apr 21, 2008 5:37 pm
by Christopher
Chris Corbyn wrote:I think I'm missing something in your example :) Can you post a longer use case? Actually, not here... I'll run along to the skeleton forum later ;)
No need. Continue on here. I think you will improve upon the design and we will learn... :)

Re: TDD workshop. Anybody welcome; Data storage abstraction.

Posted: Tue Apr 22, 2008 1:29 am
by arjan.top
Chris Corbyn wrote:
arjan.top wrote:I would start with StorageModel, then when we have final interface we use mocks on DataStore
Yeah, so there's no right/wrong way to go about this. We can use mocks before we ever write each model, or we can write the models first. I agree that we might as well jump into writing one of the Models first. I'd say to start with XML for no other reason than "it's as good a place as any".

It's fairly obvious we need to throw in our get() counterpart to set(). Then we can start testing :)

EDIT | Did those who are taking part up until now download the ZIP from earlier? Are we happy with it?
This should have been posted about 8 hours ago (before I went to bed :D ) but devnetwork was offline/working slowly ...

Yes, I downloaded it (and looked it too :) ), I am happy with it :D

And I am still not sure about StorageModel responsibilities (look at post above) ...

Re: TDD workshop. Anybody welcome; Data storage abstraction.

Posted: Tue Apr 22, 2008 2:05 am
by Chris Corbyn
Are you thinking more like DataStore doing all the getting/setting within itself, but then delegating to another component to persist any changes?

Code: Select all

class DataStore {
  get();
  set();
  save();
}
 
interface StorageBridge {
  load();
  save($data);
}
I can go that way too.

Re: TDD workshop. Anybody welcome; Data storage abstraction.

Posted: Tue Apr 22, 2008 2:06 am
by matthijs
Ok, is this a start

Code: Select all

 
<?php
require_once dirname(__FILE__) . '/../configure.php';
require_once dirname(__FILE__) . '/../../classes/Datastore.php';
 
class DatastoreTest extends UnitTestCase {
    public function testAddSomethingToDatastore() {
        $data = new DataStore();
        $data->set('foo', 'bar');
        $this->assertEqual($data->get('foo'), 'bar');
    }
}
 
class Datastore {
    public function set(){}
    public function get(){}
}
 
It returns a failing test of course, but I'm not allowed to write any code yet :)

Re: TDD workshop. Anybody welcome; Data storage abstraction.

Posted: Tue Apr 22, 2008 2:11 am
by arjan.top
Chris Corbyn wrote:Are you thinking more like DataStore doing all the getting/setting within itself, but then delegating to another component to persist any changes?

Code: Select all

class DataStore {
  get();
  set();
  save();
}
 
interface StorageBridge {
  load();
  save($data);
}
I can go that way too.
That's what I had in mind yes, DataStore would store an array of values, Bridge is responsible for converting ...

If that is OK of course :wink:

Re: TDD workshop. Anybody welcome; Data storage abstraction.

Posted: Tue Apr 22, 2008 2:14 am
by arjan.top
matthijs wrote:Ok, is this a start

Code: Select all

 
<?php
require_once dirname(__FILE__) . '/../configure.php';
require_once dirname(__FILE__) . '/../../classes/Datastore.php';
 
class DatastoreTest extends UnitTestCase {
    public function testAddSomethingToDatastore() {
        $data = new DataStore();
        $data->set('foo', 'bar');
        $this->assertEqual($data->get('foo'), 'bar');
    }
}
 
class Datastore {
    public function set(){}
    public function get(){}
}
 
It returns a failing test of course, but I'm not allowed to write any code yet :)
It won't be OK i think, you are trying to test set and get, none of them is implemented yet

Re: TDD workshop. Anybody welcome; Data storage abstraction.

Posted: Tue Apr 22, 2008 2:44 am
by Chris Corbyn
arjan.top wrote:It won't be OK i think, you are trying to test set and get, none of them is implemented yet
Well, that's sort of the point. It's test-driven so the failing test is our specification for what we have to code. If we're going down the DataStore as a simple container delegating to a persistence layer then what matthijs posted is right.

Let's just establish where we're putting this code first.

In classes/DataStore.php:

Code: Select all

<?php
 
class DataStore {
  public function set($key, $value) {
  }
  public function get($key) {
  }
}
 
In tests/unit/DataStoreTest.php:

Code: Select all

<?php
 
require_once dirname(__FILE__) . '/../configure.php';
require_once dirname(__FILE__) . '/../../classes/DataStore.php';
 
class DataStoreTest extends UnitTestCase {
  public function testAddSometingToDataStore() {
    $data = new DataStore();
    $data->set('foo', 'bar');
    $this->assertEqual($data->get('foo'), 'bar');
  }
}
 
And in tests/AllTests.php:

Code: Select all

<?php
 
require_once dirname(__FILE__) . '/configure.php';
 
class DataStoreTestSuite extends TestSuite {
  public function __construct() {
    parent::__construct('All DataStore tests');
    $this->addFile(TEST_BASE . '/unit/DataStoreTest.php');
  }
}
This produces a failure:

Code: Select all

AllTests.php
1) Equal expectation fails as [NULL] does not match [String: bar] at [/Users/chris/data_store/tests/unit/DataStoreTest.php line 10]
    in testAddSomethingToDataStore
    in DataStoreTest
    in /Users/chris/data_store/tests/unit/DataStoreTest.php
    in All DataStore tests
FAILURES!!!
Test cases run: 1/1, Passes: 0, Failures: 1, Exceptions: 0
Before we continue I'd just like to bring something up. The name of the test method... can we improve it? Is it really describing what we're testing? ;)

Re: TDD workshop. Anybody welcome; Data storage abstraction.

Posted: Tue Apr 22, 2008 2:50 am
by Chris Corbyn
We are missing something though matthijs. We never discussed instantiating the DataStore without a constructor. We have a dependency on StorageModel right? (Sorry, I keep changing its name... can we pick one? :P).