tags:

views:

338

answers:

5

I am working on a class library using C#. I have designed 3 main classes to help model our data. They are designed such that class A contains a list of class B instances, and class B contains a reference to a class C instance, ie:

public class Policy
{
    public List < PolicyTerm > myTerms;
    person Customer;
    string PolicyNumber;
}

public class PolicyTerm
{
     public Billing myBill;
     Datetime effectivedate;
     List < Activities > termActivities;
     public doAction()
     {
          use value from Policy, like PolicyNumber;
     }

}

public class Billing
{
    float remainingBalance;
    Datetime nextDueDate;
    public void doSomething()
    {
         reference value from PolicyTerm, such as effective date;
         use value from Policy, such as PolicyNumber;
    }
}

The problem I have is when I try to use a method within PolicyTerm or Billing that needs data from the containing class. In the example above, this would be the method "doSomething" trying to use a value from PolicyTerm, like the effective date for the term in requesting or saving data to our database.

I am wondering if I have the correct design for my classes because of this scenario. Should I just add a reference to the "parent" class within the child classes, in order to make the parent's data available? Or do I need to rethink the overall structure and design of the code?

I feel like the class design works well for modeling the data and our business rules, but it does create a few limitations like the above situation. I liked the separation of the PolicyTerm and Billing for the ability to allow that code to be modified and tested independently. Also, I feel like it keeps each section smaller and simpler.

Any advice that can be provided would be much appreciated.

Update: Code block was updated to provide more details on the code in question.

A: 

Creating a reference to your required class doesn't seem a bad idea at all. If it's required, you could make Class C's constructor take the reference to Class B and store it in a member variable.

I'm working on a project at the moment with a couple of classes behave like this.

Another option which might be a bit more "sane" is to have an event on class C, that's something like "SuchAndSuchDataRequired." Class B could then listen to that event when it gets the instance of C. Class C fires the event from within doSomething() when it needs the data from B, B then returns the data in it's event handler and bingo - class C has the data and doesn't even know it came from class B.

Andy Shellam
I like the idea of events, but that might be more complicated than it needs to be. Again, it all depends on what exactly he's trying to do.
Brian T Hannan
A: 

The general rule of thumb is keep the data as close as possible to the functions/methods/classes that will be using it. This will keep things decoupled and you won't have to have both classes referencing each other, which actually makes you have to create an extra object that might not be necessary.

And like ChaosPandion said: please post some more specific code so we can better help you.

Edit:

If you B references C and C references B, then you might want to consider putting the two together as one object. This works best if the two classes are not completely different. If there is no real distinguishable difference, then just put it together in one class ... that could simplify the whole thing.

Brian T Hannan
The code was updated to provide more details. I agree that PolicyTerm (class B) and Billing (class C) are closely related to each other, but I feel like it is nice to have them as separate classes.
Swoop
+1  A: 

This really depends on the situation. In general, unless there is a clear, obvious relationship between classes "B" and "C", it's a red flag that C.doSomething() would require access to B, since C is contained within B...

However, a method in B requiring access to C makes sense, since C is a member within B.

That being said, there are times that this is appropriate. Without knowing your actual classes, and what they represent, its difficult to say more...

Reed Copsey
Question was updated to provide more details. I agree about the red flag comment. While I can get the code to work, I feel like something isn't right.
Swoop
@Swoop: In your case, it almost seems like Billing should be part of Customer, and Billing.doSomething should be passed a PolicyTerm as an argument...
Reed Copsey
+3  A: 

If doSomething() always needs the reference to the C object's parent, you should indeed put this reference into C where you can ensure that it refers to the correct B instance. OTOH if that reference is not always the parent, but still it is always going to refer to the same B instance, it still suggests turning it into a member of C. OTOH if doSomething() can be called with varying references, that reference should be kept as a method parameter.

It is not bad per se to put a reference from child to parent, or to have a mutual dependency between two classes - it depends on the context. The consequence of this is that the two classes can not be used separately, so in fact they form a component. This may or may not be acceptable for you.

Components in general can consist of multiple classes - a collection with its items and iterator(s) is in fact a typical example. However, it is advisable to express the logical dependency between these classes on the physical level as well, e.g. by making one class an inner class of the other, or making both classes inner classes in a third class.

Péter Török
+1  A: 

Two classes shouldn't, but two interfaces is OK.

Of course, the smaller the interfaces the better. You'll find that if the interfaces are small enough (which they should be - see Interface Segregation Principal), you won't actually need 2 of the same.

Steve Dunn