3

I was wondering what is the best practice for accessing the owner instance when using composition (not aggregation)

public class Manager
{
    public List<ElementToManage> Listelmt;
    public List<Filter> ListeFilters;

    public void LoadState(){}
}

public class Filter
{
    public ElementToManage instance1;
    public ElementToManage instance2;

    public object value1;
    public object value2;

    public LoadState()
    {
    //need to access the property Listelmt in the owner instance (manager instance)
    //instance1 = Listelmt.SingleOrDefault(...
    }
}

So far I'm thinking about two possibilities:

  1. Keep a reference to the owner in the Filter instance.
  2. Declare an event in the Filter class. The manager instance subscribe to it, and the filter throw it when needed.

I feel more like using the second possibility. It seems more OOP to me, and there is less dependencies between the classes ( any refactoring later will be easier),

But debugging and tracing may be a bit harder on the long run. Regarding business layer classes, i don't remember seeing events for this purpose.

Any insight would be greatly appreciated

Bombinosh
  • 413
  • 6
  • 18

3 Answers3

1

There is no concept of an "owner" of a class instance, there should not be any strong coupling between the Filter instance and the object that happens to have an instance of it.

That being the case an event seems appropriate: It allows for loose coupling while enabling the functionality you want. If you went with option #1 on the other hand you would limit the overall usefulness of the Filter class - now it can only be contained in Manager classes, I don't think that is what you would want.

Overall looking at your code you might want to pass in the relevant data the method LoadState operates on so it doesn't have to "reach out".

BrokenGlass
  • 158,293
  • 28
  • 286
  • 335
  • I think there is a concept of strict ownership regarding composition : check this post: [link](http://stackoverflow.com/questions/885937/difference-between-association-aggregation-and-composition) If i choose the option #1, i could cast the owner instance as an interface (Iowner). The manager class would inherit from Iowner, and the Iowner interface could expose the property i need (Listelmt). Like that, the Filter class is not only usable in the manager class. I prefer the option #2 too, but i think the issue TcKs pointed out is relevant – Bombinosh Mar 16 '12 at 16:12
1

I recomend the reference to owner of filter instance. The event can be handled by more handlers and can change result of previous handler(s). And you propadly don't want change the owner during lifetime of Filter without notification the Filter instance.

TcKs
  • 25,849
  • 11
  • 66
  • 104
  • you got a point. i could overcome this if i use a delegate instead of event, and if i prevent multicasting. It's possible, but seems complex to me. – Bombinosh Mar 16 '12 at 16:22
  • Every delegate can be multicast. The events do by default "Delegate.Combine()" and "Delegate.Remove()" for "+=" and "-=", but if you provide only the delegate, the consumer of your API can do that manualy. – TcKs Mar 16 '12 at 16:33
  • For example "filter.GetOwner = (GetOwnerDelegate)Delegate.Combine(filter.GetOwner, this.MyGetOwnerMethod);" will make the delegate as multicast delegate. – TcKs Mar 16 '12 at 16:35
  • yes, i got that. I was thinking about preventing multicasting. let's say i execute only the delegate of the first subscriber. Well, it's lame isn't it? – Bombinosh Mar 16 '12 at 16:50
0

My short answer : Neither.

First option to keep a reference to the owner is problematic for several reasons. Filter class no longer has a single responsibility. Filter and Manager are tightly coupled. etc.

Second option is only a little better, and yes I've used events in similar scenearios, it rarely if ever ends well.

It's difficult to give a definite advice without more specific details. Some thoughts:

1) Are you sure your classes are as they should be? Maybe there should be a class to compose a single ElementToManage and a single Filter ?

2) Who is responsible for creating a Filter? For example, if it is Manager, maybe the Manager can give the list as a construction parameter? Maybe you can create a FilterFactory class that does any needed initializations.

3) Who calls filter.LoadState()? Maybe the needed list could be passed as a parameter to the LoadState() method.

4) I frequently use an "Initialization Design Pattern" (my terminology) For example I'll have a BinaryTree where parent and child will point to each other. The Factory constructs the nodes in a plain state, and than calls an initialize method with other needed objects. The class becomes complicated because I probably need to ensure that an uninitialized object raises an error for every other usage, and need to ensure that an object is initialized only once, is initialized only through the Factory, etc. But if it works, it is usually the best solution, in my opinion.

5) I'm still trying to learn "Dependency Injection" and getting nowhere, I guess it may have something to do with your question. I wonder if someone will come with an answer involving Dependency Injection.

Ali Ferhat
  • 2,511
  • 17
  • 24
  • the classes are almost set in stones... the creation is handled by an other class ( some persistance manager). The thing is, i need to implement something quickly, and we were debating about these two possibilities. Dependency Injection is too big for this purpose. – Bombinosh Mar 16 '12 at 16:42