Mark Brouwer wrote:
Bob Scheifler wrote:
Rick Moynihan wrote:
Briefly, my main issue with these classes (and I guess other parts of
Jini) is that code which uses these classes is hard to unit test
because they don't have interfaces.
If the issue is just unit testing, what prevents you from simply writing
your own alternate implementations of the classes and linking them in?
I know the question was for Rick, but nevertheless I like to take the
opportunity to react.
Thanks for this, as your response is largely in line with my views and
experience on the matter. I also seem to have neglected to respond to
this question.
Around the 'expectation' the contract of some important functionality is
specified as an interface a bunch of tools have been developed, for
example a product such as EasyMock (for more info read
http://today.java.net/pub/a/today/2006/06/20/getting-started-with-easymock-2.html,
haven't used it so don't know whether it is handy or not). Also things
as Google Guice and other DI frameworks most times use in their examples
interfaces instead of classes that can be extended, resulting in a
mindset that interfaces is what people expect for DI (note I'm not
saying this is correct).
I have no experience in using EasyMock or anything along those lines,
instead preferring to create my own mock's where possible. And I can't
say that the experience of wrestling to make mocks out of the Jini
classes was rewarding.
I'm also partial to dependency injection, and find the technique
particularly useful, primarily because it helps to support unit testing.
Again, I've not been using a special DI framework for this.
Instead I have found that Commons Digester can deliver this
functionality, and for me works particularly well:
http://jakarta.apache.org/commons/digester/
But my main argument against alternate implementations (by extension
that is), is that you often end up with those nasty constructors that
require proper arguments which you don't have or don't want to provide
or that even might fail at construction time. Together with all the
environmental assumptions that lie in the implementation of the class
you are extending, also you might drag in a lot of code just because of
the implementation.
My experience with Jini and mocking is that it can be done, and I did
infact manage to mock out various classes (e.g. the
ServiceDiscoveryManager) for my purposes. Here (as Mark suggests) I
used extension to create my MockServiceDiscoveryManager class. I then
added a few extra methods to allow me to configure different
expected/unexpected behaviors into the implementation.
I must admit that It didn't occur to me that I could have just created
my own implementation of the class in the SDM namespace and linked it in
at runtime. Unfortunately I think this approach is problematic as it is
likely that to get a decent test coverage the developer will want to
actually provide multiple implementations of the mock, i.e. one that
throws RemoteExceptions, one that behaves correctly etc... It seems to
me that the right place to determine which class to use is the test, not
the build script. Developers may also want their mock SDM to be named
in a manner that indicates the mocks behaviour e.g.
RemoteExceptionThrowingServiceDiscoveryManager.
Regarding Dependency Injection, you ideally want to remove knowledge of
the implementation until runtime. Unfortunately with the Jini classes
as they stand this isn't really possible.
Another example I've mentioned before is the partitioning of
responsibilities on LookupDiscoveryManager also makes this awkward
because their is no interface that unifies *ALL* the responsibilities of
the class (other than the class itself).
Interfaces gives an ultimate freedom and allow for minimal dependencies
and I don't see why we can't factor out some of the functionality of SDM
e.g. into an interface, do you Bob?
None of this stuff is particularly hard, and I don't mean to be picky,
as there are clearly ways around some of these issues. My problem is
only that these things could all be a bit easier. If River is going to
break API's for the repackaging to org.apache, why not also clean up
these issues through introducing a few interfaces etc?
If these issues can't be resolved, would it be worthwhile creating
configurable mock implementations of these Jini classes??
--
Rick Moynihan
Software Engineer
Calico Jack LTD
http://www.calicojack.co.uk/