Sign in to follow this  

Is this a circular dependancy?

This topic is 4165 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

THIS THREAD HAS CHANGED FROM A PREVIOUS ONE, PLEASE SCROLL DOWN TO MY NEXT POST THAT IS HEADED LIKE THIS ONE. ---------------------------------------------------------------------------- I am programming a small text based game. I have a Game class, which stores a list of GameCharacters. Each GameCharacter is assigned an ActionScript. The ActionScript object acts as an AI for the GameCharacter. Since the ActionScript needs to make informed decisions, it needs to know of the goings on in the Game, so it needs the game object to run method calls on. As of now, I have a circular dependency: Game--includes-->GameCharacter--includes-->ActionScript-->Game And it works, but I am not all to sure how lol... I am looking for a way to get rid of this dependancy. Here is one solution I thought of: When creating an ActionScript object, assign it pointers to all of the relavent Game information. Here is why I am not doing this: It would give each ActionScript full control of over other objects that (logically) only the Game object should be interfacing with, such as access to other GameCharacters information. This just seems like a violation of control logic. Another solution I thought of: When creating an ActionScript object, pass it a pointer to a Game member function, Game::GetGameStatus(). Here is why I am not doing this: 1) I am rather confused on how to implement it, and the compiler errors are not all to helpful. 2) This also seems like a C++ violation but I can place my finger on why... It just seems like poor design to me. Another solution I thought of: I could create a class ActionScriptInterface. And in this class have virtual functions which will return lists of information. I then would have the Game class extend the ActionScriptInterface, and have the ActionScript class know of the ActionScriptInterface. This would break the overall circular dependancy. But it also seems like poor design and it really shouldn't be needed. So my questions are, which options are good and bad and why? Is there a trick for doing something like this? Thanks, -sevans [Edited by - Sevans on July 20, 2006 8:53:34 PM]

Share this post


Link to post
Share on other sites
The best solution I can think of is not between the ones you described. In my engine, all components are comunicating between them using messages. So there is a global Dispatcher that receives messages of all kinds (derived from a base class) and put them in a queue and there are subscribers that are subscribed at the Dispatcher for specific message types. Then the dispatcher takes all messages and send them to all it's subscribers, and there is also a subscriber interface that is implemented by each subscriber which contains a ProcessMessage function, so each one will know what to do with the message. Implementing such a system is pretty easy and you can use your ActionScripts as subscribers and you can call the ProcessMessage method from the Dispatcher for each subscriber and send it the message that could contain maybe the gamestate or some other usefull and more specific information, so you cand avoid overhead.

Share this post


Link to post
Share on other sites
So, an example of this in action for one turn of the player would be:

(Let me note here that I have an Action class too which stores information about what action the ActionScript decideds to take. I failed to mention this earlier, because it was not relavent.)

So Game shoots a message to the MessageDispatcher saying its time for GameCharacter player1 to act. The MessageDispatcher then sends the message on to the GameCharacter player1 (because it is subscribing to this type of message) informing it that it is time to act, and has all of the needed information to act attached to the message. The GameCharacter player1 decides what Action it would like to take and then Sends a message back to the MessageDispatcher with the Action. The MessageDispatcher then sends that message off to the Game object because it is subscribing to that kind of message. The Game object decides what objects are affected and how, and then sends messages to the MessageDispatcher for each of the affected objects, containing how the are affected.

Does it seems like I have it down?

I do have a question though:
when a message is created, by lets say the Game class, does the Game class assign a type to this message? that would make sense so that way there can be different subscribers for different messages, but how are these message types stored? I was thinking in a hash within the MessageDispatcher, how did you do it?

This is where I was going towards with my original implementation, kind of, having the Game class being the MessageDispatcher and the messages be Action objects.

I really appreciate the input and I will most likely choose something like this, but I would love to hear more ideas yet.

EDIT: how does everyone else feel about meeshoo's implementation?

Thanks,

-sevans

[Edited by - Sevans on July 20, 2006 2:14:44 PM]

Share this post


Link to post
Share on other sites
I don't think your original design is problematic. Sometimes, circular dependencies do arise in natural ways, and I'd consider this to be one of them. It's quite common in parent/child relationships that when the parent creates the child it will pass the child a pointer to itself so that it can be used as a service provider.

Share this post


Link to post
Share on other sites
Wow really? I mean that makes sense I have just never been told that, and despite the taboo on circular dependancies I do agree with you.

Anyone else have any ideas or suggestions?

oh and
@meeshoo I think your method is great, but it actually seems like a little much for a turn based game such as mine. I don't think that constant game updates and then screen refreshes are anything I should be getting into in text based. But I am still going to try and adapt the idea. I have one more question though, you have a Global message dispatcher? so you can just call Dispatch( Message msg ); without any object being referenced? how does this fair as far as style and security are concerned though?

Share this post


Link to post
Share on other sites
In turns of style it is a good approach. In terms of security, why are you worrying about security? Security is not something you worry about in a game. If someone wants to break your code at the moment they can do it pretty easily.

Share this post


Link to post
Share on other sites
THIS IS THE BEGINNING OF THE NEW TOPIC OF THIS THREAD
----------------------------------------------------------------------------

I am confused as to whether the following is considered a circular dependancy:
When a game object is created it initializes a MessageDispatcher object that itself and other game objects subscribe to, to recieve messages. To recieve messages itself, Game implements the Subscriber interface so it must know of the MessageDispatcher. I want to know if the relationship between Subscriber, Game, and MessageDispatcher is still considered circular?
Here is a little chart I drew up when I was trying to plan this all out myself, please forgive any stupid mistakes, it wasnt meant for others eyes :)

Game object relation chart

Thanks,

-sevans

Share this post


Link to post
Share on other sites
I think you're really over-engineering this. There's nothing wrong with objects dealing with each other, and the only major problem with circular dependencies is in getting them to compile properly. Once you've overcome that, if you're happy with the design, stick with it. Don't add in a load of extra classes and interfaces to get around it. Your initial plan - Game, Character, Actionscript - is fine. You don't need a load of intermediate classes. Give your scripts a pointer to the game, ensure that Game has the relevant accessors, and you're done.

Share this post


Link to post
Share on other sites
Your diagram confuses me. How can Subscriber implement message processing methods if it does not know your message objects? And how can Game extend Subscriber without knowing its objects or including it?

And, for the record, I agree with Kylotan.

Share this post


Link to post
Share on other sites
Quote:
Original post by superpig
I don't think your original design is problematic. Sometimes, circular dependencies do arise in natural ways, and I'd consider this to be one of them. It's quite common in parent/child relationships that when the parent creates the child it will pass the child a pointer to itself so that it can be used as a service provider.


This is a quick slap of my own personnal opinion about circular dependencies (let's call them CD, I'm lazy today) [smile] (same thing for Kylotan's comment, BTW)

As many of you knows, I tend to disagree with the notion of "natural circular dependencies". Composition is natural, not CD. CD arise when your forget to apply the Dependency Inversion Principle (pdf) and the Single Responsability Principle (pdf). Your code no longer depends on an abstraction but instead depends on the actual implementation because the implemntation have too much responsabilities and is the prefered entry point for the game information. This may lead to various problems, including difficulties to apply the Open/Closed Principle (pdf).

If I have a look to your original design, I have the feeling that Game looks like a God Class, which knows everything about everyone. Of course, to share its knowledge, the Game members have to know the Game itself, and this is typically why your circular dependency happens.

However, since your design is pretty simple, it is also rather easy to remove this dependency by cutting some responsabilities from Game - namely, it should not handle the action script context, meaning that another object do - call it ActionScriptContext. Game knows the script context, so do the ActionScript instances. Our design becomes

class Game {
ActionScriptContext mScriptContext;
std::vector<Character> mCharacters;
};
class ActionScriptContext {
// references the characters in the Game object
std::vector<Character*> mCharacters;
someOtherVariables;
};
class Character {
ActionScript mScript;
};
class ActionScript {
// references Game::mScriptContext
ActionScriptContext *mScriptContext;
};


(BTW, you should leanr about UML and the corresponding class diagrams - they help a lot)

Voilà, no circular dependencies. Not perfect though (why not encapsultaing this list of character? would be better IMHO), but a good start.

Regards,

Share this post


Link to post
Share on other sites
I know UML already, I just drew this up quick for my own purposes to see where the dependancies stood, rather than worry about how I was going to have the classes interface together with members and methods and such.

@Driv3MeFar
Well I thought the fact that a class extends another implies that it includes the file, but I guess not everyone could see that. Also, Subscriber does know of Message, I simply forgot to show the relation from the subclasses of Subscriber to Message. Like I said it was just meant for my eyes when I created it.

@Emmanuel Deloget
So ActionScriptContext would contain all of the needed information that normally game would contain to interface with ActionScripts? Makes sense. Thank you for an answer to the first posts topic, it is really what I needed to hear. I never would have thought to just break Game up and remove some control from it.

But no one answered my question. Is that relationship in my diagram between Game MessageDispatcher and Subscriber a circular dependancy? Before the forums here I had never heard of a circular dependancy because the design of our programs in school is usually so obvious and avoids these. I guess the Profs know better than to assign something that may encounter them. That is a poor way to teach IMHO.

Thanks guys,

-sevans

Share this post


Link to post
Share on other sites
Sorry I've been quite busy. So let' get them one at a time.

In my approach, the Dispatcher is actually global and it is part of a Kernel, and every object has a reference to this Kernel(the core of the engine). Yes I have a Message Type enumeration and a Message base class which includes only an attribute of type MessageType. That's how the dispatcher can identify what kind of messages it is dealing with. If an object is subscribed to only one type of message then you don't even have to check the message type, you just downcast the message object to the type you are expecting, and that is coming of course with additional data specific to each message type.

You can for example, derive all your classes from a general base class, that includes a reference to the Message Dispatcher and has the ProcessMessage virtual method. Doing this, you can use the Message Dispatcher globaly and the Dispatcher doesn't have to know which class is dealing with, because they all have the virtual method implemented and they all have the same base class. Using polimorphysm in C++ is one of the most powerfull feature of this language, so there is nothing wrong having a lot of class hyerarchies.

I agree with Emmanuel Deloget, there is no overengineering in this and it takes only a few hours to get it done. The advantages and disadvantages of good/bad software design are always showing their faces when the implementation is almost done or when adding new features, and by then is to late to change it. Then everything transforms into hacks and specific workarounds. I have to say that, in my case, being a CS engineer, I like to have very clean designs. However, Sevans's simple game could be very easy extended with cool graphics and stuff, if there is a very clean design. An internal messaging system can be used (like FSM's for example) in a lot of situations, like AI, input and others and in my opinion always when developing software, you have to think of reusability and general design.

Share this post


Link to post
Share on other sites
Thank you meeshoo, I agree 100% with that, and that is why I am pushing so much with this. I really want to exhaust all possiblities. This game most likely won't even come into being. I am just exploring types of implementation, I think this is my weakest point because of the way I have been taught. And don't worry about the slow reply, you have no obligation to me ^.^d

-sevans

Share this post


Link to post
Share on other sites
Quote:

But no one answered my question. Is that relationship in my diagram between Game MessageDispatcher and Subscriber a circular dependancy? Before the forums here I had never heard of a circular dependancy because the design of our programs in school is usually so obvious and avoids these. I guess the Profs know better than to assign something that may encounter them. That is a poor way to teach IMHO.


It is circular dependency, and there is a rule that says "circular dependency implies a class". In this example, that class is something like Emmanuel's proposal.

One very real problem arised with circular dependencies in a pool game I made recently: Like you, I had a Game class, that, among other things like players,scores,cuestick,etc included some balls. For collision detection, balls referred to the Game class so they could know about other balls. So I couldn't use the Ball class without the Game class, but I thought it wasn't a big deal, since it all worked, I mean why would I want to use a Ball outside of the Game?

Until I started implementing AI. For those purposes, I needed to "test" some shots the computer was calculating to see what result they would have, and choose the best one to be actually played. In other words, I needed to use the collision code with some "virtual" balls that behaved exactly like the real ones, but not actually displaying anything and not affecting the actual game state in any way. Problem was, Ball was depedent on Game, so I couldn't create a seperate set of virtual balls without creating a new Game! I resorted to hacks like saving the real balls position into temp objects, using the Game to actually let the computer test a number of shots into the background, and restore the balls when all was done. If the Collision() module would depend on only a BallCollection module instead of the whole Game module, I would have been able to implement it more elegantly.

In your case, I would just create 2 structures: one ActionScript_OUT and one ActionScript_IN. Their use would be obvious: The script would use ActionScript_IN to "learn" the things it's allowed to know, and return in ActionScript_OUT the results(like the actions the character is supposed to make). Whatever higher-level module uses ActionScript, it just has to "feed" it with ActionScript_IN and use the data returned in ActionScript_OUT. What is that higher-level module and how does it use the data? ActionScript doesn't care.

Share this post


Link to post
Share on other sites
Perfect Mikeman, that is very nearly what I decided on with the message dispatcher, there is a seperate sending and recieving class.

However for my game, since it is turn based, I decided not to use the messaging system. I decided to use the ActionScriptContext idea. It basically acts as a communication interface between the Game and the ActionScript AIs.

Thanks for all the input,

-sevans

Share this post


Link to post
Share on other sites

This topic is 4165 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this