Namespaces in classes

Started by
35 comments, last by Holy Fuzz 18 years, 9 months ago
Instead of namespaces inside of a class, what about classes inside of a namespace?
namespace ParticlePhysics{   class Particle   {   public:      void UpdatePhysics();      void UpdateFade();      void DieOut();      void StartFloating();   };} 
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
Advertisement
Quote:I have a large, complex class that is very flexible and does many different things.

There's a word for that in Object Oriented Programming: It's called Low Cohesion, and it's a sign of a bad design. I know you didn't create this thread to get critical feedback on your design, but you should really look into this, and why it can be a bad thing.
The primary intent of namespaces is to provide a mechanism for partioning class, struct, function, and other definitions to eliminate naming conflicts. Examples would be classes contained in the STL. Without namespaces you may end up with conflicts classes such as list, string, and exception. The syntax and more importantly how the compiler handles namespaces isn't very applicable inside of a class declaration. If parts of the language were changed to support this type of declarations the amount of resulting ambiguity in the use of namespaces would in all likelyhood degrade it's usefulness.

From what I can tell the only real reason you are wanting to do this is because of the auto completion feature in the IDE you are using (no it's NOT part of the 'compiler'). This is really the wrong reason for even considering doing such a thing. The suggestions and/or criticism concerning how your classes are design should be considered as constructive and good advice - especially since they are coming from a large group of VERY experienced individuals. Considering that you are working with a very large class that includes a wide set of complex operations you really should consider breaking it down into multiple classes containing sets of specific operations.
Perhaps the reason it's considered bad design is lack of organizing code tools? I have no problem with critical feedback, but the only advice I've seen so far was to use classes to seperate tasks that my object can perform. That does provide the grouping of that single routine type, but at a messy cost. In the end, I have twenty really tiny classes that are exclusive in their use to characters and share tons of data with each other. I fail to see how this is an improvement.

Sure, I can build a class that controls the character's eyes to look around, and a class to enable or disable control systems, and a class to handle path node updates. Also a class for moving equipment into and out of hands, inventory and the invironment. Another class to handle equipping suits, checking suit compatibility, updating suit dependencies, and updating their effect on the character (note that I already have a suit class, but now I'll have a CharacterSuitManagement class). Then my characters have something called "action events". These are ways that characters can interact with the world. For example, they could walk into an area trigger and an action event is presented to them for them to make a choice. There are three functions dealing with and managing action events. I already have an ActionEvent type class, but now I'll have CharacterActionEventManagement class. You might say that a three function routine isn't enough of a reason to want change, but you soon change your mind when there are 20 routines that all have three functions. There are several routines for standing, about five for moving, three or four for climbing on ledges, only two for aiming ranged weapons, and a few for updating directions - movement, facing, and looking are all seperate states that are updated individually.

Almost every task in this class can be grouped by it's purpose, but it doesn't fit into another class. It doesn't make sense as one. If I'm mistaken, please enlighten me.
Quote:Original post by Helter Skelter
From what I can tell the only real reason you are wanting to do this is because of the auto completion feature in the IDE you are using (no it's NOT part of the 'compiler').

Forgive my IDE/Compiler wording mixup, that was very inexcusable of me.
Quote:Original post by Jiia
Perhaps the reason it's considered bad design is lack of organizing code tools?


That's like blaming a word processor for bad grammar. Design has nothing to do with languages, tools, or even specific compilers. Even low level designs have an abstraction above their actual implementation.

Quote:I have no problem with critical feedback, but the only advice I've seen so far was to use classes to seperate tasks that my object can perform.


You've only provided a minimal amount of information. In deciding which functionality should be moved to a different class you really have to decided where that functionality really belongs. Take a file parser for instance. I may create a class that reads from a file, turns each symbol into a token, and then acts on specific sequences of tokens. If I ever want to change that class to parse text that is already loaded in memory I either replace the file reader OR include additional code to handle in-memory specific parsing.

Alternatively I can take each group of functionality and place them in separate classes to make it more extensible. In doing this I may create a stream class (called FileStream) to handle input, a single class that reads from the stream and converts the input into tokens (called Tokenizer), and a class which acts on token stream do to specific operations (called Parser). Now if I want to add support to parse information already in memory I create a new stream type class (called MemoryStream) which gets passed to the tokenizer. In short I can add, replace, or change existing components without breaking the others or having to modify them to support the changes.

You just need to look at your overall design, separate functionality into logical blocks, then decide whether inheritence or composition is more applicable to how everything works together.


Quote:Almost every task in this class can be grouped by it's purpose, but it doesn't fit into another class. It doesn't make sense as one. If I'm mistaken, please enlighten me.


Maybe it does maybe it doesn't. That's the entire reason posters have suggested you revisit your design and decide if chances are necessary. Design is not simple nor is every design decision obvious. I'm sure that if you posted specific examples (i.e. your class definitions) with sufficient information about dependencies, use, and relationship others on the forum will be more than happy to make suggestions and possibly even provide a step by step blow of why they make certain decisions.
Quote:Original post by Helter Skelter
Quote:Original post by Jiia
Perhaps the reason it's considered bad design is lack of organizing code tools?

That's like blaming a word processor for bad grammar.

It's more like blaming the height restriction of my skyscraper on the building materials. (edit: By code-tools, I was referring to tools in code, not tools to work with code. IE, language features)

Quote:You've only provided a minimal amount of information.

How much information do you need? There's a lot of functions in a class, and that gets confusing. How difficult is that to follow? If there were a way to group functions by purpose, it would be much more manageable. Or at least I would think so.

Quote:In deciding which functionality should be moved to a different class you really have to decided where that functionality really belongs.

It belongs where it's at. That's why I put it there. I have no grudge against writing new classes, but it makes no sense in most of these situations.

Quote:Alternatively I can take each group of functionality and place them in separate classes to make it more extensible. In doing this I may create a stream class (called FileStream) to handle input, a single class that reads from the stream and converts the input into tokens (called Tokenizer), and a class which acts on token stream do to specific operations (called Parser).

Let's look at it from another angle. Lets say your parser includes several string management functions. Just three or four to compare, convert, search, or whatever. Then say it has a few error checking routines to see if things are going bad with the stream. Multiply this type of growth by twenty, and you have what I have. And it's still growing rapidly. You're telling me to create a class to search, manage, and convert parser strings from it's stream, even though the class will contain no data and only has three functions. The stream would also need sent to the class for each function.

Quote:Design is not simple nor is every design decision obvious. I'm sure that if you posted specific examples (i.e. your class definitions) with sufficient information about dependencies, use, and relationship others on the forum will be more than happy to make suggestions and possibly even provide a step by step blow of why they make certain decisions.

I don't have time to edit the source enough to be decent for posting. My IDE font is very small, so my comments run really far to the right. That means the source box will explode and you'll have a 5000 pixel wide thread page. It really is a huge class, hence the reason I'm looking to improve it's managment. The class declaration itself is about 200 lines of code.

Like I said, I appreciate the help. I'll find my own way around it.
Quote:
How much information do you need? There's a lot of functions in a class, and that gets confusing. How difficult is that to follow? If there were a way to group functions by purpose, it would be much more manageable. Or at least I would think so.


The people in this thread have been trying to tell you that your design is at fault here, not the language.

It turns out that there is a construct for grouping functions by purpose that is very managable in this scenario - they're called classes.


Quote:
I have a large, complex class that is very flexible and does many different things.


You created a large class with multiple responsibilities. Why don't you move the functionality of this class into several other classes and use your ParticlePhysics class as a facade (that's basically an interface class)?
Sorry if I'm being dumb (I don't use inner structs very often), but can't you use inner structs instead of namespaces to do what you want? I know there are some (compiler related) problems when determining scope rules for inner structs (e.g. in the following example some compilers won't let ParticlePhysics::Particle::UpdatePhysics() access or modify a ParticlePhysics::m_doo). Try it out and see what you get:

class ParticlePhysics{public:    // ...protected:    struct Particle    {       // doesn't modify state       static void UpdatePhysics();       // ...    };    struct Whatever    {        // modifies state        void Bar();       // ...    private:       int m_choo;    } whatever;    // note: Whatever has state - requires instanceprivate:    int m_doo;};class MadBugger : public ParticlePhysics{public:    void Update()    {        // static method        Particle::UpdatePhysics();        // ...        // instance method        whatever.Bar();    }};


Sometimes better code readability and usability require 'unpopular' methods to get the job done; remember that everyone here is only trying to help (in a very general way), albeit without the wider understanding of the scope, overall design, or implications of what you have presented here. Good luck! [smile]

Edit: improved example to show inner struct semantics with and without state, and need to have instance of ParticlePhysics::Whatever; also made inner structs protected

[Edited by - ajones on July 21, 2005 3:40:42 AM]
Quote:Original post by Jiia
By code-tools, I was referring to tools in code, not tools to work with code. IE, language features.

Regardless, programming languages have nothing to do with bad design.
Quote:If there were a way to group functions by purpose, it would be much more manageable. Or at least I would think so.

Ummmm...that's what classes are for.
Quote:Let's look at it from another angle. Lets say your parser includes several string management functions. Just three or four to compare, convert, search, or whatever.

that depends. If the string functions can be considered general purpose they will most likely end up in a utility class, string class, or in their own little section of the program. Support for strings is broad enough that they in all likelyhook belong elsewhere.
Quote:Then say it has a few error checking routines to see if things are going bad with the stream.

That functionality belongs in the appropriate stream class. All the parser cares about is if data is available or the end of input has been encountered.
Quote:Like I said, I appreciate the help. I'll find my own way around it.

Good luck.

This topic is closed to new replies.

Advertisement