In your case, it should be easy to build a fake version of the web
service, run it in an embedded HTTP server in your test and point you
system to talk to it. You can make the fake service give predictable
responses so that you have repeatable tests and give it a nice API do
that the tests are easy to read and write.
--Nat
This is Nat's blog entry about Simplicators - http://www.natpryce.com/articles/000785.html
one way to look at it is that Simplicators are an implementation of a Hexagonal's Adaptor. The protocol from the application to the Simplicator is the port. The additional complexity is that it's in a separate process.
S.
No.
An Impersonator provides "an implementation which mimics the exact
protocols and semantics of those environments while requiring minimal
resources and providing full control over execution and managed data."
A Simplicator is used when it is not practical to implement the protocol.
--Nat
I guess so, though I don't think the word "injected" describes what is
going on or the design thinking involved.
OO design is concerned with inside vs outside. An object hides and
encapsulates its implementation details inside its boundary and
provides a messaging protocol for use by objects outside its boundary.
In the book we term this "internals vs peers" and "context
independence".
This inside vs outside thinking can apply all the way up and down.
Objects are made up of and composed into objects. Ports and Adapters
applies inside vs outside thinking at the process scale. Gateways and
Simplicators at the system scale.
The protocols change as the scale changes: function calls, event
queues, RPC, messaging, HTTP. As does the way of composing parts. But
the ideas of distinguishing between published access protocol and
internal implementation details and context independence remains
valuable.
--Nat
Peers are what I stub or mock--which depends on whether it's a query or action. I tend to test internals through the containing object, with maybe some more precise direct testing of the internal object.
> And a practical example of "context independence" could be wrapping a
> library behind an interface to take away the dependency to details the
> class should and need not to know about. Right ?
yes.
> What is not yet clear to me if from a design point of view the
> distinction between the process scale and the system scale is needed/useful.
> For example .NET provide automatic proxy to call objects cross a
> process boundaries. What is different in the coarse-grain of the
> public interface and the communication that can be asynchronous.
> Again, I'm double-checking that I'm understanding correctly what you
> mean.
Not sure what the question is here. There's a famous paper about the fallacies of distributed computing that points out how we can't ignore the network.
http://en.wikipedia.org/wiki/Fallacies_of_distributed_computing_(Deutsch)
S.
On Nov 19, 9:51 am, Steve Freeman <st...@m3p.co.uk> wrote:
> On 18 Nov 2011, at 22:55, Luca Minudel wrote:
>
> > Reading here your comments about "inside vs outside" and "internals
> > vs peers" and "context independence" finally I got a overall
> > understanding of these terms and I can map them with the term "levels
> > of abstractions" that I'm used to from the C++ Stroustrup's book.
> > From a practical point of view internals vs peers has to do with
> > deciding where to stub and where to mock. Right ?
>
> Peers are what I stub or mock--which depends on whether it's a query or action. I tend to test internals through the containing object, with maybe some more precise direct testing of the internal object.
>
Still have a doubt about the term internals.
In the example of the Receiver at page 230 of the GOOS there is the
test RejectsRequestsNotWithinTheSameDay() where the object Clock is
considered an internal of Receiver (... we’ve made it obvious that
Receiver is dependent on time—we can’t even create one without a
Clock. Some argue that this is breaking encapsulation by exposing the
internals of a Receiver...) and the test Clock is stubbed.
If I got it right sometime internals like Clock can also be stubbed,
but never mocked.
> ...
>
> Not sure what the question is here. There's a famous paper about the fallacies of distributed computing that points out how we can't ignore the network.
>
> http://en.wikipedia.org/wiki/Fallacies_of_distributed_computing_(Deutsch)
Thanks, also to Giorgio for the interesting links!
I see the point here and I recognize the differences between local and
remote objects and interfaces.
When I look at the hexagonal architecture pattern it seams to me that
the pattern make sense also when adapters and ports are at the system
level, not just at the process level.
The Clock exists outside (and before) the Receiver and is passed to
the Receiver when the Receiver is constructed. Therefore it is NOT an
internal of the Receiver. It is a peer of the Receiver.
"Internals" are internal implementation details that are not visible
from outside an object that uses them. From outside the object,
there's no way of telling what internals exist, how they are
constructed or used, what their lifetimes are, etc. Therefore they
cannot be mocked or stubbed. Client code cannot rely on them, and so
does not break when they are changed (loose coupling).
--Nat
Now think I got the definitions used in the goos for Peer and
Internals, probably I should collect the info/definition from this
thread and write it somewhere.
Personally when I code I also see objects that are in between of
Internal and Peer:
- like an Internal they share the lifetime of the containing object
(like Receiver in the book example), they are used only by the
containing object, they are not exposed in any way in the public
interface of the containing object (as property, parameter type or
return type of some public member)
- like an Internal, a different implementation of the containing
object could not make use at all of that "internal" object or could
use a completely different one
- like a Peer they are injected into the container object throw the
parametric constructor (like Clock in the book example)
One situation where I end up with that kind of object is when the
containing object do not have/need to know the details/info that are
needed to instantiate that "internal" object. So I inject it and I
delegate the instantiation to someone else.
Does this make sense ?
How would you call/classify this kind of objects ?
Luca
On Nov 20, 9:59 pm, Nat Pryce <nat.pr...@gmail.com> wrote:
Sorry Luca but I lost you, can you do an example? From what you wrote
you're describing the Peer to me.
The Clock can be reused in many other objects of different classes
that need to read the time and it's not given that will die together
with the Receiver.
Uberto
I mentioned Clock and Receiver as example to clarify things ... but
the example made the sentence more confuse :D
Indeed I was not talking about the Clock that is a Peer as you pointed
out, nor I'm talking about the Receiver.
Instead I was talking about a kind of object that is not exactly a
Peer and neither an Internal as defined by Goos because
- have 2 of the characteristics of an Internal (same lifetime or less
of his container, is an internal implementation detail that can vary
for different implementation strategies)
- have 1 characteristic of a Peer (is injected in the containing
object through the constructor).
Let's try with an example.
Think about and object GameController that execute a user command and
to do this needs to retrieve info about user preferences, the object
that retrieve the user preference is called ... UserPreferences
UserPreferences is used only by the GameController, every instance of
GameController have it's own instance of UserPreferences that can be
disposed together with the GameController. And UserPreferences is not
exposed by GameController in any way in the public interface. Here
UserPreferences looks to be an Internal of UserPreferences.
UserPreferences can have different implementations, can retrieve info
from a Cookie, from a file in the file-system, from and Oracle db or
from a SqlServer db.
For the cookie it need to know the cookie name, for the file-system it
need to know the path with the filemane, and for the DBs it need to
know their connection strings that differs between Oracle and
SqlServer.
The decision of with concrete implementation of UserPreferences to use
is not made by GameController, is made elsewhere. GameController just
need to use it.
So GameController don't have/need to know about the cookie name or the
file path or the connection string. That's why this knowledge is
elsewhere and so UserPreferences is instantiated and injected into
GameController through the parametric constructor. Internals are not
injected via the constructor, so here UserPreferences looks to be a
Peer.
Do you agree that UserPreferences is not exactly a Peer as defined in
the goos and it neither an Internal as defined in the goos ?
How would you call/classify this kind of objects then ?
Luca
On Nov 27, 5:03 pm, Uberto Barbini <ube...@ubiland.net> wrote:
This distinction is useful to me because I find advantages in not
mocking these objects that are implementation details (even when
passed in through the constructor) :
- I find more interesting to describe with mocks in the unit tests the
interaction between object peers at a level higher then low level
implementation details
- I find more practical to stub these objects because the interaction
with these objects is more subject to unimportant changes: with a stub
the test have more chases not to fail after the changes while a mock
will likely fail even when there is no bug nor a behaviour change that
I'm interested to describe in a test (with stubs the expected
behaviour is tested throw the containing object)
To rephrase it, I find this distinction useful in order to identify
some of the objects that is preferable to stub them instead of mock
them because the interactions with those objects is not a useful focus
for a unit test.
I guess that you use other ways/criteria for this or you use a
different approach. If you have link, can point me to some paragraph
of the book or if you can tell, I'm curious to know.
Luca
On Nov 29, 5:13 pm, isaiah perumalla <isaiahperuma...@googlemail.com>
wrote:
> Maybe this is bit of a simplistic view but to me if you are passing it in
> via the public api then it cant be an internal, to me internals are objects
> hidden inside and are not visible to clients via the public api, in your
> example Userpreference to me this is a peer as it would be inappropriate
> to hide this inside the object as it could depend on external environment
> such at filesystem or db it would not context independent.
We agree on this , it is a Peer as described in the goos book.
> "I find advantages in not
> mocking these objects that are implementation details (even when
> passed in through the constructor) :..."
> The way I think about this, is that messages send to collaborator that
> cause side effects and message sends which are queries asking for info. not
> every thing passed via constructor needs to be mocked, we could pass in
> fake or stub as you mentioned, as they usually tend to be queries that are
> idempotent . But if any of the messages send to the collaborators cause
> side effect then it makes sense to verify these messages via mocks
>
When the contained object receive a message and there is a side effect
on it (and not on the containing object) I usually end up testing it
with a mock too.
So looks like here we are doing in similar ways.
When we are interested into that side effect on the contained object,
looks like the containing object have a responsibility toward the
contained object.
In this case I will not call the contained object an implementation
detail but more like a Peer (so yes, mocking is an option here).
In the end, the distinction I'm doing for the objects that are
implementation details and still passed to the constructor, is to
define criteria to decide where is better to mock and where to stub
(when there is a choice of course:)
Luca
> When the contained object receive a message and there is a side effect
> on it (and not on the containing object) I usually end up testing it
> with a mock too.
ok this is a "real" peer.
but when there is no side effect on the contained, like in your
example, I think you can simply pass an immutable value object
(configuration in your case).
That's why you prefer to stub them during testing.
In case of Decorator and Strategy peers, I prefer to test them using mocks.
Those
Uberto