473,382 Members | 1,786 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

Parellel interface and class hierarchies

Take a class, RateTableProductCode. It needs to share implementation with
other classes, so the common code is placed in a ProductCode class, from
which it derives. There needs to be an IRateTableProductCode interface so
that objects can be mocked for testing. That interface also has a common
interface which is shared with other interfaces, and that goes in
IProductCode. This all makes sense to me, but I just have a nagging feeling
that such a parallel hierarchy is unnecessary.

interface IProductCode { void foo(); }

class ProductCode : IProductCode { void foo() {} }

interface IRateTableProductCode : IProductCode { void bar(); }

class IRateTableProductCode : ProductCode, IRateTableProductCode { void
bar() {} }

And of course:

interface IRateRecordProductCode : IProductCode { void zam(); }

class IRateRecordProductCode : ProductCode, IRateRecordProductCode { void
zam() {} }
May 15 '06 #1
6 1616
"Mark Wilden" <Ma********@newsgroups.nospam> wrote:
Take a class, RateTableProductCode. It needs to share implementation with
other classes, so the common code is placed in a ProductCode class, from
which it derives.


Just a suggestion: have you considered using composition instead of
inheritance for code reuse? When inheritance is used for something other
than polymorphism, it can lead to strong coupling where it isn't
warranted.

Don't forget that inheritance is one of the strongest couplings and thus
possible source of future brittleness that you can create in your
design.

On the actual topic of making testing easier: I recommend you try to
establish a directed acyclic graph of dependencies between classes. That
way, you can first build tests around the "leaf" dependencies. Once
those have tests around them, you can move on to those classes which
depend on the tested classes, and so on.

If you can get your architecture to be layered and modularised, you
should be able to get a situation where only the few cycles in
dependencies need to have interfaces for mockups.

I would also consider looking at using abstract base classes instead of
interfaces, for several reasons: interfaces are more brittle (e.g. add a
method and it has to be added everywhere), and you can put preconditions
etc. in public methods on the abstract base classes, and keep the
abstract methods protected.

-- Barry
May 15 '06 #2
"Barry Kelly" <ba***********@gmail.com> wrote in message
news:qc********************************@4ax.com...
"Mark Wilden" <Ma********@newsgroups.nospam> wrote:
Take a class, RateTableProductCode. It needs to share implementation with
other classes, so the common code is placed in a ProductCode class, from
which it derives.
Just a suggestion: have you considered using composition instead of
inheritance for code reuse? When inheritance is used for something other
than polymorphism, it can lead to strong coupling where it isn't
warranted.


Good point. I will eventually go that way. I'm working on refactoring legacy
code that already has the class hierarchy. The difference between one child
of ProductCode and another is simply the way it parses an Excel file, and
I'm going to convert that to a strategy.

I've introduced the interface hierarchy to support NMock tests. I'm new to
NMock, but I understand it's preferred to mock interfaces rather than
classes (if indeed that's even possible).
Don't forget that inheritance is one of the strongest couplings
I never thought about it that way. You're right, of course.
On the actual topic of making testing easier: I recommend you try to
establish a directed acyclic graph of dependencies between classes. That
way, you can first build tests around the "leaf" dependencies. Once
those have tests around them, you can move on to those classes which
depend on the tested classes, and so on.
My dependencies in this case are compositional. A ProductCode belongs to a
Product. I've finished testing ProductCode. Now I'm testing Product, but I
don't want to have to support the calls Product makes to ProductCodes, so I
mock out the ProductCodes.
If you can get your architecture to be layered and modularised, you
should be able to get a situation where only the few cycles in
dependencies need to have interfaces for mockups.
I'll definitely keep that in mind.
I would also consider looking at using abstract base classes instead of
interfaces, for several reasons: interfaces are more brittle (e.g. add a
method and it has to be added everywhere), and you can put preconditions
etc. in public methods on the abstract base classes, and keep the
abstract methods protected.


More good stuff.

Again, I'm only using interfaces at all because I believe NMock requires
them.

///ark
May 15 '06 #3
Barry Kelly <ba***********@gmail.com> wrote:

<snip>
On the actual topic of making testing easier: I recommend you try to
establish a directed acyclic graph of dependencies between classes. That
way, you can first build tests around the "leaf" dependencies. Once
those have tests around them, you can move on to those classes which
depend on the tested classes, and so on.


That makes testing a lot harder than mocks do, however. For instance,
it may be very hard to simulate a situation where your real classes
will throw a particular exception, or it could be that the real classes
use other resources such as databases or files which aren't desirable
in test cases. Mocks provide a really handy way of pretending that
data/error conditions are occurring without having anything actually
behind them. (They also allow you to develop the thing using the
interface before the implementation of the interface, which can
occasionally be handy.)

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
May 15 '06 #4
Jon Skeet [C# MVP] <sk***@pobox.com> wrote:
Barry Kelly <ba***********@gmail.com> wrote:

<snip>
On the actual topic of making testing easier: I recommend you try to
establish a directed acyclic graph of dependencies between classes. That
way, you can first build tests around the "leaf" dependencies. Once
those have tests around them, you can move on to those classes which
depend on the tested classes, and so on.
That makes testing a lot harder than mocks do, however. For instance,
it may be very hard to simulate a situation where your real classes
will throw a particular exception, or it could be that the real classes
use other resources such as databases or files which aren't desirable
in test cases.


Sure. I forgot to mention that I find mockups more useful at module
boundaries than at every class boundary - places where there is some
natural bottleneck so there is less disruption to the class architecture
to allow this replaceability.
(They also allow you to develop the thing using the
interface before the implementation of the interface, which can
occasionally be handy.)


I typically do the simplest thing that works first. When a class has the
right responsibilities, it's easy to later refactor it later to make it
an abstract base class / concrete subclass pair, and then create new
concrete subclasses, when the need for that presents itself.

-- Barry
May 15 '06 #5
"Barry Kelly" <ba***********@gmail.com> wrote in message
news:qm********************************@4ax.com...
Sure. I forgot to mention that I find mockups more useful at module
boundaries than at every class boundary - places where there is some
natural bottleneck so there is less disruption to the class architecture
to allow this replaceability.
I've been drinking the mock kool-aid, which says that mock-driven
development is a different kind of programming than merely using them to
write tests. The main article that has influenced me is "Mock Roles, not
Objects".
I typically do the simplest thing that works first. When a class has the
right responsibilities, it's easy to later refactor it later to make it
an abstract base class / concrete subclass pair, and then create new
concrete subclasses, when the need for that presents itself.


Doing the simplest thing that works is a very powerful concept, but it
applies at a different level than TDD. Writing tests first is clearly not
the simplest way to program, yet I can't imagine a better way for me to
work.

That said, I have long disagreed that every class needs an associated
interface. In fact, I wish NMock would work without them. I think it was
Martin Fowler who pointed out that every class does in fact have its own
interface built-in.
May 15 '06 #6
"Mark Wilden" <Ma********@newsgroups.nospam> wrote:
That said, I have long disagreed that every class needs an associated
interface. In fact, I wish NMock would work without them. I think it was
Martin Fowler who pointed out that every class does in fact have its own
interface built-in.


I remember somebody saying this, it might have been him.

Specifically on the mock approach to testing, it looks hard to do
without language or runtime support. I don't think interfaces are the
right tool. Maybe some kind of low-level proxy technique if the runtime
permitted it, to redirect class definitions to mock-ups - although that
could open up security issues if it was fully general. I've never yet
had the opportunity to really dig into the proxying mechanism behind
..NET remoting yet, so I don't know how powerful it is.

A general approach of having a class "implement" the public interface of
another class and be fully polymorphically replaceable would imply
virtual dispatch everywhere. I think you could only support it at the
relatively low level of replacing the class's implementation throughout
the appdomain or process. The idea I have in my mind is Java's class
loaders, which allow you to load arbitrary bytecode for each and every
class. However, every class loaded from a particular class loader gets
its dependencies loaded from the same class loader (IIRC
Class.getClassLoader() is used), which means you kind of end up with a
parallel universe for each class loader. You can reduce that by
delegating to other class loaders, IIRC.

-- Barry
May 15 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

31
by: grahamo | last post by:
This came up in an interview I did a while ago and I wanted to know the correct answer. The setup is this; If I have a base class "food" and also two classes "meat" and "veg" that inherit from...
0
by: Arne Claus | last post by:
I've got a tricky problem here. I try to create an object-hierarchie, based on a template base class like template <class T> class Node { addChild(Node<T> *) =0; // the Node-Container wil be...
18
by: Bradley | last post by:
I'm trying to determine if there's a general rule for when an Interface should used vs. an Abstract Class. Is there any design advantage to using one or the other? Brad
15
by: mr.peteryu | last post by:
Hi, Can someone explain the idea behind casting to an interface? For example: -> I have an IInterface that contains a Read() method. -> I have an object "obj" that implements IInterface. ...
6
by: thomson | last post by:
Hi I do have an Interface, which is implemented in lot of places, My question is i observed that After quite some time if i need to add a new method in the interface , i need to do a lot of...
11
by: Darren.Ratcliffe | last post by:
Hi guys Posted what was probably a rather confusing post about this the other day, so I am going to have another go and see if I can make more sense. This sis purely a I've got a base class...
4
by: Raja Chandrasekaran | last post by:
Hai friends, I really wonder, If the interface does not have any definition, Y do we need to use interface. You can then only we can use Multiple inheritance. I really cant understand, Just for...
15
by: Xah Lee | last post by:
On Java's Interface Xah Lee, 20050223 In Java the language, there's this a keyword “interface”. In a functional language, a function can be specified by its name and parameter specs....
15
by: Robert Brown | last post by:
Is there a good approach to modelling many heterogeneous entity types with that have some attributes in common? Say I have entities "employees" which share some attibutes (e.g. firstname,...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.