Avoiding cycles with interfaces [modified]
-
Hello, I have a situation where I have a cycle: Group <>---- Contact ..........-----<> I have the class Contact which has name (eg. John), addr, etc. And the class Group which has a name (eg. Friends) and a list of contacts List<contact> The thing is that I want the Contact to know what groups contain him For example lets say I have the groups Family, Friends, Job and they all contain John (and others) I want that these groups contain John and that John knows he is member of these groups. I want to avoid the cycle, Should I use an Interface? or maybe other solution?
modified on Wednesday, April 15, 2009 6:14 PM
-
Hello, I have a situation where I have a cycle: Group <>---- Contact ..........-----<> I have the class Contact which has name (eg. John), addr, etc. And the class Group which has a name (eg. Friends) and a list of contacts List<contact> The thing is that I want the Contact to know what groups contain him For example lets say I have the groups Family, Friends, Job and they all contain John (and others) I want that these groups contain John and that John knows he is member of these groups. I want to avoid the cycle, Should I use an Interface? or maybe other solution?
modified on Wednesday, April 15, 2009 6:14 PM
come on... no one?
-
Hello, I have a situation where I have a cycle: Group <>---- Contact ..........-----<> I have the class Contact which has name (eg. John), addr, etc. And the class Group which has a name (eg. Friends) and a list of contacts List<contact> The thing is that I want the Contact to know what groups contain him For example lets say I have the groups Family, Friends, Job and they all contain John (and others) I want that these groups contain John and that John knows he is member of these groups. I want to avoid the cycle, Should I use an Interface? or maybe other solution?
modified on Wednesday, April 15, 2009 6:14 PM
I don't see the problem. A Group holds zero, one or more Contacts. and each Contact wants to hold a list of all the Groups it belongs to. So a Group either *is* a list, or *contains* a list. and a Contact contains a list. IIRC that is called aggregation: putting information (list of Groups) in members of the class (Contact). Refinement: I didn't provide type information for the lists; it could be that: a Group either *is* a list, or *contains* a list of Contacts. and a Contact contains a list of Groups. or you could define a common ancestor for Group and Contact, and use that type as the type held in both lists (Inheritance). Conclusion: I don't need interfaces to "break" the cycle, there wasn't really a cycle if you ask me. If you insist on having an interface, how about IListable; both Group and Contact implement IListable (not sure what the functionality would be though); and both lists could contain IListables. :)
Luc Pattyn [Forum Guidelines] [My Articles]
Avoiding unwanted divs (as in "articles needing approval") with the help of this FireFox add-in
-
I don't see the problem. A Group holds zero, one or more Contacts. and each Contact wants to hold a list of all the Groups it belongs to. So a Group either *is* a list, or *contains* a list. and a Contact contains a list. IIRC that is called aggregation: putting information (list of Groups) in members of the class (Contact). Refinement: I didn't provide type information for the lists; it could be that: a Group either *is* a list, or *contains* a list of Contacts. and a Contact contains a list of Groups. or you could define a common ancestor for Group and Contact, and use that type as the type held in both lists (Inheritance). Conclusion: I don't need interfaces to "break" the cycle, there wasn't really a cycle if you ask me. If you insist on having an interface, how about IListable; both Group and Contact implement IListable (not sure what the functionality would be though); and both lists could contain IListables. :)
Luc Pattyn [Forum Guidelines] [My Articles]
Avoiding unwanted divs (as in "articles needing approval") with the help of this FireFox add-in
Hi, thanks for replying!.. "there wasn't really a cycle if you ask me." The cycle is between Contact and Group.. We've been told in University that we have to avoid these cycles because of dependency and coupling (which I don't see but was hoping that someone here could tell me).. An example where I can see the solution more clearly is for example a Car that contains an Engine, and the Engine must notify the Car that contains him something.. One solution, the one I have to avoid is: Car contains Engine, Engine contains Car In that case one would put an interface ISomething (Car : ISomething) and the Engine instead of having a Car would have an ISomething The difference might be that the Engine must do something on the Car (turn it on for example). And here, the contact doesnt have to do anything on the group and viceversa. Am i right? Should i go with the cycle anyway?
-
Hi, thanks for replying!.. "there wasn't really a cycle if you ask me." The cycle is between Contact and Group.. We've been told in University that we have to avoid these cycles because of dependency and coupling (which I don't see but was hoping that someone here could tell me).. An example where I can see the solution more clearly is for example a Car that contains an Engine, and the Engine must notify the Car that contains him something.. One solution, the one I have to avoid is: Car contains Engine, Engine contains Car In that case one would put an interface ISomething (Car : ISomething) and the Engine instead of having a Car would have an ISomething The difference might be that the Engine must do something on the Car (turn it on for example). And here, the contact doesnt have to do anything on the group and viceversa. Am i right? Should i go with the cycle anyway?
In the car-engine situation, I would do: car contains an engine, and is fully aware of its functionality, not its internals of course. engine knows nothing about cars, but holds one or more public events (.NET speak), where an event is a list of delegates, a delegate basically is a function pointer or a callback. So the car tells the engine it is interested in some events; the car engine signals those occurrences through the appropriate event, without knowing anything about the subscriber(s); all it knows is the syntax of the delegate (number and type of parameters, there normally is no return value). Again no interface is involved; although you could achieve the same with an interface (your ISomething, I would say IAmInterestedInSomeEngineStuff). The advantage of events is they can hold and serve multiple listeners without the engine even being aware of that. :)
Luc Pattyn [Forum Guidelines] [My Articles]
Avoiding unwanted divs (as in "articles needing approval") with the help of this FireFox add-in
modified on Thursday, April 16, 2009 11:06 PM
-
Hi, thanks for replying!.. "there wasn't really a cycle if you ask me." The cycle is between Contact and Group.. We've been told in University that we have to avoid these cycles because of dependency and coupling (which I don't see but was hoping that someone here could tell me).. An example where I can see the solution more clearly is for example a Car that contains an Engine, and the Engine must notify the Car that contains him something.. One solution, the one I have to avoid is: Car contains Engine, Engine contains Car In that case one would put an interface ISomething (Car : ISomething) and the Engine instead of having a Car would have an ISomething The difference might be that the Engine must do something on the Car (turn it on for example). And here, the contact doesnt have to do anything on the group and viceversa. Am i right? Should i go with the cycle anyway?
In my opinion, also if you ask your profs, you should avoid cyclic dependencies between assemblies but not between classes. You should try to minimize coupling but you can not avoid it altogether. Afterall, the classes need to communicate with each other to accomplish whatever needs to be accomplished. You can create an interface and you can always do so but remember you still have a cyclic dependency but it is less direct. Now you are tied to something which implements the interface. If you never want to allow contact creation without group, then do not allow its creation unless from within the group: Contact c = aGroup.NewContact() and Group will call contact's constructor. Cyclic dependency is bad between assemblies because of compilation race.
CodingYoshi Visual Basic is for basic people, C# is for sharp people. Farid Tarin '07
-
Hello, I have a situation where I have a cycle: Group <>---- Contact ..........-----<> I have the class Contact which has name (eg. John), addr, etc. And the class Group which has a name (eg. Friends) and a list of contacts List<contact> The thing is that I want the Contact to know what groups contain him For example lets say I have the groups Family, Friends, Job and they all contain John (and others) I want that these groups contain John and that John knows he is member of these groups. I want to avoid the cycle, Should I use an Interface? or maybe other solution?
modified on Wednesday, April 15, 2009 6:14 PM
Interesting topic. It is very frustrating when interfaces express very complicated dependencies between objects. Cyclic dependencies may result in endless loops and weird state control. An interface specifies a unidirectional 'control panel': You can use it to push and pull, but you have the initiative and don't want be interrupted while using the interface. However, if cycles exist between interfaces (or between objects), you may be interrupted each time you try to operate a certain object via an interface. If this happens a lot, you have spaghetti code. Our world is full of interconnected objects that control each others, so what to do about these when modeling them in software? A very simple example is a Nut and a Bolt. Sometimes the Nut turns the Bolt and sometimes the Bolt turns the Nut. Lets say an interface for both Nut and Bolt is
ITurnable
and it contains aturn(float angle)
method. No interface cycle exists. Now, if Bolt is turned, it decides whether an attached Nut should be turned or not. Likewise, if Nut is turned, it decides whether an inserted Bolt should be turned or not. These decisions are implementation specific, and it may be that Nut and Bolt call each other recursively, but theITurnable
interface is clear about direction of control. Yes, I know. The Bolt and Nut need to be connected, if they should know something about each other e.g. friction, or if they should be able to turn each other; how could that be expressed with interfaces? A) Interface for a made up object. You can make a fictional interface that ties a Nut and a Bolt e.g. anIConnection
implemented by a 3rd class e.g.Connection
. If a Nut actively unscrews itself, it will direct control to theIConnection
implementor that is responsible for letting the Bolt know. B) Interface for existing objects. You can implement an attach/detach interface for Nut and Bolt e.g.IConnector
implemented in both classes. This interface could just have anattach(IConnector connector)
and adetach(IConnector connector)
method. Again the direction of control is clear, and it is specified viaIConnector
that Nut and Bolt can be interconnected. C) Interfaces for existing objects. You can implement attach/detach in interfaces of Nut and Bolt e.g.INut
andIBolt
, respectively.INut
could have anattach(IBolt bolt)
and a