17 Mar, 2010, KaVir wrote in the 61st comment:
Votes: 0
Deimos said:
What does that have to do with World handling what boils down to world logic? If "who" gives you a list of online players, what contains that list? World (or whatever your equivalent is).

The players might not be in the "world" either, if (for example) they don't have bodies. They might just be accounts with channel access.
17 Mar, 2010, David Haley wrote in the 62nd comment:
Votes: 0
I think that "World" here is being used to represent "the big universe master control thingy". I also use "world" in that sense to represent global game state and other management, and not the tangible game world that players move around in. (That said, were I to redo it, I would probably call it something different.)
17 Mar, 2010, Deimos wrote in the 63rd comment:
Votes: 0
KaVir said:
The players might not be in the "world" either, if (for example) they don't have bodies. They might just be accounts with channel access.

Er.. my terminology is probably confusing you. By "world" I mean "the big universe master control thingy."**

I really wouldn't know what else to call it, though. Maybe I'll rename the class to BigUniverseMasterControlThingy. It's kind of catchy.



** Copyright (C) David Haley 2010
17 Mar, 2010, David Haley wrote in the 64th comment:
Votes: 0
I'm not sure if I should be pleased or dismayed that my monstrous name sounds catchy. :redface:
17 Mar, 2010, KaVir wrote in the 65th comment:
Votes: 0
Deimos said:
Er.. my terminology is probably confusing you. By "world" I mean "the big universe master control thingy."**

So global commands, encapsulated as you see fit but not tied to an actor? I interpreted your comment in post #52 as disagreement with the comments made in post #51, apologies if that wasn't the case.
17 Mar, 2010, Deimos wrote in the 66th comment:
Votes: 0
KaVir said:
So global commands, encapsulated as you see fit but not tied to an actor? I interpreted your comment in post #52 as disagreement with the comments made in post #51, apologies if that wasn't the case.

Ahhh; no, I wasn't disagreeing with him. My post was just a general reply to earlier objections about letting the "world" handle command logic. I wanted to revisit it because most people seemed to disagree up front without really elaborating, and that confused me, since it seemed like a lot of codebases that I've seen use this approach. Now I'm thinking that maybe this was because they were thinking of "world" in the tangible sense, as well? Like I said, I don't really know what else to call it, though. I've seen it dubbed "Game" or "GameController" before. Maybe something like that is more appropriate. Shrug.
21 Mar, 2010, Tyche wrote in the 67th comment:
Votes: 0
I do not use exceptions in Ruby for program flow control. (i.e. door locks)
I use exceptions for error detection.
21 Mar, 2010, flumpy wrote in the 68th comment:
Votes: 0
I have several control entities, I call mine mini me… Er.. I mean command interpreter, as it does do some parsing…
23 Mar, 2010, shasarak wrote in the 69th comment:
Votes: 0
Deimos said:
shasarak said:
The Spellcast would then do things like:

- Check to see if the caster actually knows the spell in question
- Calculate how many mana points the spell will cost
- Determine whether the caster casts the spell correctly
- If he does, deduct points from his mana total
- Create and initialise a spell-effect object
- Apply the spell-effect to the target

Yes, this is the type of "overseeing of the process" that I'm referring to. On an atomic level, there would be several different classes involved in the process, but something has to organize all of this piecemeal logic into steps that actually perform the command. You advocate an instanced class for doing this. Is there a reason you would choose this over, say, a universal SpellManager class that handles casting for everyone? I guess I don't see the benefits.

I never got around to answering this, did I?

Yes, there are any number of advantages to not having a SpellManager singleton control stuff like this.

For example, is there any aspect of the casting of one spell which depends strongly on what happened during a previous spell-cast? There might be - perhaps if two different spell-casters cast the same spell within 60 seconds of each other, regardless of who and where they are, the impact of the second spell is weakened because the universe has not yet recovered its magical equilibrium and recharged its magical energy reservoirs. If that happens, then clearly something somewhere needs to track not just a single spell-cast but all of them, and handle the interactions between the different casts. However, it's more likely that the casting of one spell is not affected by the casting of others; the effects of the spells may well interact additively, but the processes of casting and the creation of the effects are independent. If you use a single object which handles multiple casts, and persists between casts, then you're giving that object more information than it needs to do its job: its function is to handle a single cast successfully, but it knows about more than one. When an object does more than it needs to do, or has access to more information than is required to do its job, that's usually a sign of design problems.

In terms of practical effects, you also need to think about implementation details and code readability. Think about how the SpellManager maintains its state, for example. One possibility is for the SpellManager to handle absolutely everything in one giant method; but that makes the code very hard to read and understand. The function of well-written code should be obvious at a glance; a high-level method invokes lower-level methods whose names make it clear what they do. In well-written OO code, methods are typically no more than half a dozen lines long.

Another approach would be for the object to track state by passing dozens of different parameters around between functions; that, again, makes for very poor code legibility, and is one of the things good OO code avoids - rather than having multiple arguments being passed from method to method, you wrap it all up inside an object, and make those passed values instance variables, so each method that needs them has access to them via the state of the object itself. (In well-written OO code it is a little unusual to pass more than one argument into a method, and rare to pass more than two).

So, can the SpellManager use its instance variables to track its state? The process of casting a spell is probably not always instantaneous - it may require 2 or 3 ticks between someone starting to cast a spell and it taking effect. That means that someone else can cast a new spell before the SpellManager has finished processing the previous one. So your SpellManager singleton object needs to be able to handle multiple spell-casts simultaneously, with each one being in a different state. Immediately, therefore, we've added a huge amount of complexity: instead of an object that tracks the casting of a spell, we have to make one which tracks the casting of multiple spells at the same time. Maybe it can store its state values on dictionaries, keyed by the spell in question - but why make things difficult for yourself? If different spell-casts are actually supposed to be independent processes, why not model them like that?

A related question:
Deimos said:
To be honest, I don't really see why allowing World to handle this kind of logic is so bad. I look at it like a chessboard, with the tiles being rooms, and the pieces being creatures. The pieces don't move themselves. They require a ominously looming presence to control them and everything they do (World). Shrug.

Well, for starters, this analysis is wrong: during a game of chess it is not the world that moves the pieces, but the players. :smile: However, that shouldn't necessarily influence us.

A good place to start when modelling a chess game would be to write down some classes that correspond to what you actually see. So, let's have a class for a piece, a class for a square, a class for the board (which initialises and holds a collection of squares), a class for a player, perhaps a class for a clock. You then move onto slightly more abstract concepts; for example you might have a class whose job it is to represent the type of move a piece can make (so any given piece has one of those as a property). It will also almost certainly be worth having a class which corresponds to a move: its properties might be the piece that is moving, perhaps the player making the move (although that can maybe be derived from the piece), the square the piece moves from, the square it moves to, the piece captured (if any), and whether or not the result of the move is a check, or some game-ending condition such as checkmate or stalemate. A collection of such moves provides a record of the game so far.

A good hint that having a class which represents a move is useful comes simply from thinking about how chess works. A move is a fairly distinct, self-contained entity. There is a clear real-life process which has a defined beginning and end, followed by a new process beginning which is distinct from the previous one (i.e. the next move). Casting a spell on a MUD is clearly the same type of thing: it's a self-contained process, with well-defined properties (caster, spell, target), and separate from any similar action; so it makes sense for the application to model it as a distinct entity.

With all due respect, when you ask questions like this, you are essentially challenging the benefits of the whole OO paradigm. In the extreme case of having "The World" handle spell-casts, you are effectively abandoning OO programming altogether and having a single, huge procedural programme do absolutely everything (spell casting, movement, etc.)

An awful lot of clever people have spent an awful lot of time over the course of several decades figuring out the benefits of OO, and it is reasonable to assume that, by now, they have, between them, come up with some useful ideas! While it is certainly important to understand the context in which any given OO feature is desirable (e.g. inheritance is a very neat feature, but that doesn't mean you should always use it in preference to aggregation), it is a teensy bit arrogant to imagine that you are going to single-handedly expose OO programming as a whole as an inappropriate way of doing things.
:tongue:

In a case like this, it actually isn't necessary to specifically analyse the bad things that would happen as a result of having a SpellManager singleton handle all casts rather than a different SpellManager instance handle each one; if you apply basic OO principles of not allowing an object to do more than it needs to do, or know more than it needs to know, the correct solution just falls out of that. OO conventions are not arbitrary; they've grown up because they usually produce the right answers when you apply them; and you can save yourself a lot of time by working on the assumption that the conventions are correct until there is a good reason to suppose otherwise, instead of automatically challenging established OO knowledge at every turn.

:smile:
23 Mar, 2010, David Haley wrote in the 70th comment:
Votes: 0
Shasarak said:
With all due respect, when you ask questions like this, you are essentially challenging the benefits of the whole OO paradigm. In the extreme case of having "The World" handle spell-casts, you are effectively abandoning OO programming altogether and having a single, huge procedural programme do absolutely everything (spell casting, movement, etc.)

An awful lot of clever people have spent an awful lot of time over the course of several decades figuring out the benefits of OO, and it is reasonable to assume that, by now, they have, between them, come up with some useful ideas! While it is certainly important to understand the context in which any given OO feature is desirable (e.g. inheritance is a very neat feature, but that doesn't mean you should always use it in preference to aggregation), it is a teensy bit arrogant to imagine that you are going to single-handedly expose OO programming as a whole as an inappropriate way of doing things.

No, that's really not at all essentially what he's doing. To say that that is what he is doing, however, is akin to saying that any decision to not use OO in a given place is paramount to challenging all of OO – is that not itself somewhat arrogant? :wink:

To be honest I really don't think he made anything like the argument that "OO programming as a whole <is> an inappropriate way of doing things".
23 Mar, 2010, flumpy wrote in the 71st comment:
Votes: 0
shasarak said:
With all due respect, when you ask questions like this, you are essentially challenging the benefits of the whole OO paradigm. In the extreme case of having "The World" handle spell-casts, you are effectively abandoning OO programming altogether and having a single, huge procedural programme do absolutely everything (spell casting, movement, etc.)

An awful lot of clever people have spent an awful lot of time over the course of several decades figuring out the benefits of OO, and it is reasonable to assume that, by now, they have, between them, come up with some useful ideas! While it is certainly important to understand the context in which any given OO feature is desirable (e.g. inheritance is a very neat feature, but that doesn't mean you should always use it in preference to aggregation), it is a teensy bit arrogant to imagine that you are going to single-handedly expose OO programming as a whole as an inappropriate way of doing things.
:tongue:

In a case like this, it actually isn't necessary to specifically analyse the bad things that would happen as a result of having a SpellManager singleton handle all casts rather than a different SpellManager instance handle each one; if you apply basic OO principles of not allowing an object to do more than it needs to do, or know more than it needs to know, the correct solution just falls out of that. OO conventions are not arbitrary; they've grown up because they usually produce the right answers when you apply them; and you can save yourself a lot of time by working on the assumption that the conventions are correct until there is a good reason to suppose otherwise, instead of automatically challenging established OO knowledge at every turn.

:smile:


David's right, he's not saying that at all. It is perfectly feasible to have your code encapsulated and yet have an "overall control thingy" (controller) deal with the command chain. In fact, its a principal of most web frameworks that the "request" is handled first by a "controller" and then individual composite objects respond to that request, and you wouldn't write those procedurally now would you?

Please do not confuse "controllers" with procedural programming, it's plain silly :wink:
24 Mar, 2010, shasarak wrote in the 72nd comment:
Votes: 0
flumpy said:
It is perfectly feasible to have your code encapsulated and yet have an "overall control thingy" (controller) deal with the command chain. In fact, its a principal of most web frameworks that the "request" is handled first by a "controller" and then individual composite objects respond to that request, and you wouldn't write those procedurally now would you?

Please do not confuse "controllers" with procedural programming, it's plain silly :wink:

Given that I have spent the past 15 years doing Object Oriented programming on a professional basis for roughly 47 weeks a year, I think it is probably safe to assume I am aware of this. Of course, perhaps I'm not. Indeed, perhaps I will also be stunned when you reveal to me that Object Oriented systems sometimes use inheritance, and that programmes sometimes make use of "for" loops, because I have never encountered such advanced concepts before.

(sighs)
24 Mar, 2010, David Haley wrote in the 73rd comment:
Votes: 0
Why then did you say he was going against the entire object oriented paradigm?
24 Mar, 2010, shasarak wrote in the 74th comment:
Votes: 0
David Haley said:
Why then did you say he was going against the entire object oriented paradigm?

Because I was paying attention.

If you look at the context in which Deimos' original posts (to which I was responding) were made, it is perfectly clear what he was suggesting. He asked what should handle all the code and tests involved in a spell cast. I said you should create a new instance of a class for each cast which would model the process. He asked what were the advantages of doing that, and suggested instead (not as well) using a singleton "SpellManager" object to handle all of the spell-cast logic. I dealt with that in the first half of my long post. In subsequent posts he went on to suggest not merely using a SpellManager singleton but using a "World" singleton which handles all of the logic of spell casts and also all of the logic of movement. So I went on to elaborate on why mixing things as distinct as that into the same class is unlikely to be a good idea.

Of course, if you choose to look at the wording of his posts outside of their original context, you could interpret them as meaning something else; for example, that you should use a singleton to create instances of a SpellCast class, and have those instances handle the process. But why would you choose to do that?
24 Mar, 2010, David Haley wrote in the 75th comment:
Votes: 0
Hmm, ok. Except that, as I said in my previous reply to you here, he was considering a single instance of a single problem, not discarding OOP in general. I'm not sure why you insist on saying he's discarding everything. But ah well.
24 Mar, 2010, Deimos wrote in the 76th comment:
Votes: 0
To clarify, that was not what I was suggesting, shasarak. I pointed out in the comment that you quoted that there would, of course, be objects of various different classes handling the logic at an atomic level. To give an over-simplified example, consider the following control flow:

1) User issues command
2) Server receives user input
3) Server passes input to CommandInterpreter
4) CommandInterpreter parses command into an understandable action (<user> wants to cast <spell>)
5) CommandInterpreter tells World (or SpellManager, or whatever…) that <user> is trying to cast <spell>
6) World does error-checking to see if <user> can cast <spell> (this most likely involves several other TBD objects responding to World's requests)
7) If it's allowable, World then creates a Spell object, inserting it into its own User/Spells collection
8) Each tick, casting time is decremented (however you handle this kind of thing)
9) When the spell is finished casting, the Spell object does whatever <spell> is designed to do and World removes it from its collection

I really don't see how that's procedural. It seems very OO to me. Having a SpellManager class seems more appropriate on the surface, but I can't think of any benefit outside of organization that it would have over simply allowing World to handle this. I certainly don't see any benefit to putting the logic contained in steps 6-9 into the User/Player/whatever, outside of semantics ("player.cast(spell)" looks prettier and reads easier than "world.cast(player,spell)"). And even after reading your interesting reply, I still don't quite follow as to the benefits of instanced "SpellCast" objects to handle the logic in steps 6-9.
24 Mar, 2010, flumpy wrote in the 77th comment:
Votes: 0
Indeed that is very OO.

player.cast(spell) is what's known as domain specific syntax. This concept can be useful as it allows you think in the problem from the position of the "actors in the scene" rather than the "objects that do the job".

It's also a lot easier for non-leet-programmers to get their heads around. You can easily understand

player.say "hello there!"


over

messageObject.sendMessageToRoom(player, "$p.name says hello there", "You say hello there")


It often makes sense to allow scripting to happen in a DSL-like way because of this, and theres nothing wrong with it.

It is also very easy to implement in languages like Ruby :)

So I'd say both are fine, but perhaps hide the complexity of the pure oo when thinking about building, perhaps.
24 Mar, 2010, David Haley wrote in the 78th comment:
Votes: 0
Wait… the issue of what is used in the engine is wholly separate from what DSL might or might not be used in any exposed scripting language, no?
24 Mar, 2010, flumpy wrote in the 79th comment:
Votes: 0
Yes, did I not make that clear? Or was that aimed at someone else?

Perhaps I should have said "when thinking about builders and building" or some such.
24 Mar, 2010, Runter wrote in the 80th comment:
Votes: 0
David Haley said:
Wait… the issue of what is used in the engine is wholly separate from what DSL might or might not be used in any exposed scripting language, no?

Yes.
60.0/163