From: Vladimir Jovic on
Hello,

In the article in Lahman's blog here:
http://pathfinderpeople.blogs.com/hslahman/what_is_oo_development_all_about/
the explanation about self-containment in OO tells this:

***
As a practical matter that means that any object responsibility can be
exhaustively unit tested without implementing any other object behaviors
***

What if the system is complex, and this class handles other classes?
What are strategies for handling this case?

Since I am working in C++, I can imaging that the testing class is
implemented as a template, where the template parameters are the classes
that the tested class handles.
Or, is there other way?
This seams like a complex solution just to simplify testing.

Thanks in advance.


PS In case I wasn't clear enough, here is a simple ASCI diagram:
a -> b
\-> c -> d
\-> e
\-> f

The question : How to test class c, using stubs for classes d,e,f?
An example in c++ would be perfect, but java or other language is ok as well
From: Daniel T. on
Vladimir Jovic <vladaspams(a)gmail.com> wrote:

> Hello,
>
> In the article in Lahman's blog here:
> http://pathfinderpeople.blogs.com/hslahman/what_is_oo_development_all_about/
> the explanation about self-containment in OO tells this:
>
> ***
> As a practical matter that means that any object responsibility can be
> exhaustively unit tested without implementing any other object behaviors
> ***
>
> What if the system is complex, and this class handles other classes?
> What are strategies for handling this case?
>
> Since I am working in C++, I can imaging that the testing class is
> implemented as a template, where the template parameters are the classes
> that the tested class handles.
> Or, is there other way?
> This seams like a complex solution just to simplify testing.
>
> Thanks in advance.
>
>
> PS In case I wasn't clear enough, here is a simple ASCI diagram:
> a -> b
> \-> c -> d
> \-> e
> \-> f
>
> The question : How to test class c, using stubs for classes d,e,f?
> An example in c++ would be perfect, but java or other language is ok as well

Looking at your diagram, if 'd', 'e', and 'f' were all ints would you be
concerned with testing 'c' in isolation to them? I think not. You can be
sure that 'int' is fully tested and functions, and you rely on that fact
when testing to see that 'c' works.

Things aren't much different when 'd', 'e' or 'f' are classes that you
write, except that you have more work to do in order to make sure they
are fully tested before you can test 'c' properly.

The key to "self-containment" is that 'c' does expose its 'd', 'e' or
'f' and rely on others changing the state of them outside of itself. In
other words, your aim should be a containment relationship (as defined
by Riel, not the UML version of containment) wherever possible.

The point of containment in this sense, is that 'a' doesn't care that
'c' uses one or more 'd's to do its job, and 'c' could replace its 'd'
with something completely different without affecting 'a' in any way.
(This is one of the motivations for making all member-variables private.)

Hope this helps.
From: Vladimir Jovic on
Daniel T. wrote:
> Vladimir Jovic <vladaspams(a)gmail.com> wrote:
>
>> Hello,
>>
>> In the article in Lahman's blog here:
>> http://pathfinderpeople.blogs.com/hslahman/what_is_oo_development_all_about/
>> the explanation about self-containment in OO tells this:
>>
>> ***
>> As a practical matter that means that any object responsibility can be
>> exhaustively unit tested without implementing any other object behaviors
>> ***
>>
>> What if the system is complex, and this class handles other classes?
>> What are strategies for handling this case?
>>
>> Since I am working in C++, I can imaging that the testing class is
>> implemented as a template, where the template parameters are the classes
>> that the tested class handles.
>> Or, is there other way?
>> This seams like a complex solution just to simplify testing.
>>
>> Thanks in advance.
>>
>>
>> PS In case I wasn't clear enough, here is a simple ASCI diagram:
>> a -> b
>> \-> c -> d
>> \-> e
>> \-> f
>>
>> The question : How to test class c, using stubs for classes d,e,f?
>> An example in c++ would be perfect, but java or other language is ok as well
>
> Looking at your diagram, if 'd', 'e', and 'f' were all ints would you be
> concerned with testing 'c' in isolation to them? I think not. You can be
> sure that 'int' is fully tested and functions, and you rely on that fact
> when testing to see that 'c' works.
>

Yes, off course. Doing that makes not sense.

> Things aren't much different when 'd', 'e' or 'f' are classes that you
> write, except that you have more work to do in order to make sure they
> are fully tested before you can test 'c' properly.
>

The problem I am facing is the unit tests are becoming more and more
complex as the we go more levels down.
But is there an alternative?

> The key to "self-containment" is that 'c' does expose its 'd', 'e' or
> 'f' and rely on others changing the state of them outside of itself. In
> other words, your aim should be a containment relationship (as defined
> by Riel, not the UML version of containment) wherever possible.
>

Great. Do you recommend Riel's book to improve OO design?
I found this on the net:
http://lcm.csa.iisc.ernet.in/soft_arch/OO_Design_Heuristic.htm
(summary of OO design from Riel)

I do not understand what do you mean by "c expose d,e or f".
My colegue suggested to add a method to create instances of the
contained classes, but in my opinion that would simplify the testing,
but the class (and all contained classes) would become much more complex.
Do you mean something like this:

class E : public SomeBase1
{
//...
};
class F : public SomeBase2
{
//...
};

class C
{
//...
void UpdateClass1( SomeBase1 &obj1 )
{
// update instance of object e
}
void UpdateClass2( SomeBase2 &obj2 )
{
// update instance of object f
}

private:
SomeBase1 *e;
SomeBase2 *f;
};

> The point of containment in this sense, is that 'a' doesn't care that
> 'c' uses one or more 'd's to do its job, and 'c' could replace its 'd'
> with something completely different without affecting 'a' in any way.
> (This is one of the motivations for making all member-variables private.)
>

Ok, that means I missunderstood the self-containment. I thought it
favour the use of mock classes for d,e,f classes when testing class c.

> Hope this helps.

It does :)
From: Daniel T. on
Vladimir Jovic <vladaspams(a)gmail.com> wrote:
> Daniel T. wrote:
> > Vladimir Jovic <vladaspams(a)gmail.com> wrote:
> >
> > > PS In case I wasn't clear enough, here is a simple ASCI diagram:
> > > a -> b
> > > \-> c -> d
> > > \-> e
> > > \-> f
> > >
> > > The question : How to test class c, using stubs for classes d,e,f?
> > > An example in c++ would be perfect, but java or other language is
> > > ok as well
> >
> > Looking at your diagram, if 'd', 'e', and 'f' were all ints would
> > you be concerned with testing 'c' in isolation to them? I think not.
> > You can be sure that 'int' is fully tested and functions, and you
> > rely on that fact when testing to see that 'c' works.
>
> Yes, off course. Doing that makes not sense.
>
> > Things aren't much different when 'd', 'e' or 'f' are classes that
> > you write, except that you have more work to do in order to make
> > sure they are fully tested before you can test 'c' properly.
>
> The problem I am facing is the unit tests are becoming more and more
> complex as the we go more levels down. But is there an alternative?

I'm not sure what you mean by "levels down" do you mean d, e, and f are
harder to test than c, or that c is harder to test than d, e, and f?

Either way, if you distributed your functionality well, no class should
be harder to test than any other.

> > The key to "self-containment" is that 'c' does expose its 'd', 'e'
> > or 'f' and rely on others changing the state of them outside of
> > itself. In other words, your aim should be a containment
> > relationship (as defined by Riel, not the UML version of
> > containment) wherever possible.
>
> Great. Do you recommend Riel's book to improve OO design? I found this
> on the net:
> http://lcm.csa.iisc.ernet.in/soft_arch/OO_Design_Heuristic.htm
> (summary of OO design from Riel)

Yes, I recommend it highly.

> I do not understand what do you mean by "c expose d,e or f".

The point of a containment relationship is that it guarantees that we
can ignore the contained objects at some high level of design. In your
example above, if 'a' (and 'c's test harness) can use 'c' without
knowing that it is using a 'd', 'e' and 'f' internally, then 'c'
contains them.

As a practical matter in C++, this means that 'c' does not expose a
pointer or non-const reference to the 'd', 'e', or 'f' that it contains.

> My colegue suggested to add a method to create instances of the
> contained classes, but in my opinion that would simplify the testing,
> but the class (and all contained classes) would become much more
> complex. Do you mean something like this:
>
> class E : public SomeBase1
> {
> //...
> };
> class F : public SomeBase2
> {
> //...
> };
>
> class C
> {
> //...
> void UpdateClass1( SomeBase1 &obj1 )
> {
> // update instance of object e
> }
> void UpdateClass2( SomeBase2 &obj2 )
> {
> // update instance of object f
> }
>
> private:
> SomeBase1 *e;
> SomeBase2 *f;
> };

Again, what if they were ints? Would you feel the need to put two
"updateInt" functions in the class in order to test it? Sometimes that
is appropriate, but not often.

If anything, maybe something like this:

class C {
E e;
F f;
public:
const E& get_e() const { return e; }
const F& get_f() const { return f; }
// functions that modify e and f
};

Note that the above does *not* break containment because the functions
can easily be replace by ones that return by value, for example:

E C::get_e() const {
E result;
// set E's state appropriately using other information.
return result;
}

In languages other than C++, things get a little more complicated and it
is harder to efficiently maintain containment.
From: Vladimir Jovic on
Daniel T. wrote:
> Vladimir Jovic <vladaspams(a)gmail.com> wrote:
>> Daniel T. wrote:
>>> Vladimir Jovic <vladaspams(a)gmail.com> wrote:
>>>
>>>> PS In case I wasn't clear enough, here is a simple ASCI diagram:
>>>> a -> b
>>>> \-> c -> d
>>>> \-> e
>>>> \-> f
>>>>
>>>> The question : How to test class c, using stubs for classes d,e,f?
>>>> An example in c++ would be perfect, but java or other language is
>>>> ok as well
>>> Looking at your diagram, if 'd', 'e', and 'f' were all ints would
>>> you be concerned with testing 'c' in isolation to them? I think not.
>>> You can be sure that 'int' is fully tested and functions, and you
>>> rely on that fact when testing to see that 'c' works.
>> Yes, off course. Doing that makes not sense.
>>
>>> Things aren't much different when 'd', 'e' or 'f' are classes that
>>> you write, except that you have more work to do in order to make
>>> sure they are fully tested before you can test 'c' properly.
>> The problem I am facing is the unit tests are becoming more and more
>> complex as the we go more levels down. But is there an alternative?
>
> I'm not sure what you mean by "levels down" do you mean d, e, and f are
> harder to test than c, or that c is harder to test than d, e, and f?
>

If the system looks like this:

a -> b -> c -> d -> .... -> x -> y
-> ...
-> ...
-> ...

where all these are classes, then testing a is basically the
functionality test. But if you want to write unit tests for b or c,
things are more complicated then for example writing for x or y. Unless
you use mock classes.

> Either way, if you distributed your functionality well, no class should
> be harder to test than any other.
>

Might be a stupid question, but is there a metric or method to measure
functionality distribution?

>>> The key to "self-containment" is that 'c' does expose its 'd', 'e'
>>> or 'f' and rely on others changing the state of them outside of
>>> itself. In other words, your aim should be a containment
>>> relationship (as defined by Riel, not the UML version of
>>> containment) wherever possible.
>> Great. Do you recommend Riel's book to improve OO design? I found this
>> on the net:
>> http://lcm.csa.iisc.ernet.in/soft_arch/OO_Design_Heuristic.htm
>> (summary of OO design from Riel)
>
> Yes, I recommend it highly.
>
>> I do not understand what do you mean by "c expose d,e or f".
>
> The point of a containment relationship is that it guarantees that we
> can ignore the contained objects at some high level of design. In your
> example above, if 'a' (and 'c's test harness) can use 'c' without
> knowing that it is using a 'd', 'e' and 'f' internally, then 'c'
> contains them.
>
> As a practical matter in C++, this means that 'c' does not expose a
> pointer or non-const reference to the 'd', 'e', or 'f' that it contains.
>

Ok, this makes it clear. This basically means that class 'a' knows what
class 'b' (that is contains) is going to do, but now how.

Thank you.