Namespaces in classes

Started by
35 comments, last by Holy Fuzz 18 years, 9 months ago
Hehe, you're really going out on a limb to help me, and I really appreciate it. I still don't think my problem is coming out very clear. I'll try to give a really good example of the exact situation I want to clean up..

class MegaBadDesign{public:	// Z Buffer	void ToggleZBuffer(bool toggle);	void SetZBufferRes(float res);	void SetZBufferDepth(float depth);	void InvertZBuffer();	void FlipZBuffer();	// Stencil	void ToggleStencil(bool toggle);	void SetStencilMask(int value);	void InvertStencil();	void FlipStencil();	// Techniques	void StartTech(HANDLE tech);	void StopTech();	void LockTech();	void UnlockTech();	bool CheckTech(HANDLE tech);	// Lighting	void SetLightDir(int index, const vector &dir);	void SetLightAmp(int index, FLOAT amp);	void SetLightColor(int index, color value);	void SetShaderDir(int index, const vector &dir);	void SetShaderAmp(int index, FLOAT amp);	void SetShaderColor(int index, color value);	// Streams	void SetStream(stream *s);	bool CheckStream(const stream *s);private:	APIShaderObject m_Thing;};

This is still just a taste, but hopefully it's pointing in the right direction. My opinion, this would be a cleaner way to name the z buffer section:

...	// Z Buffer	void ZBuffer_Toggle(bool toggle);	void ZBuffer_SetRes(float res);	void ZBuffer_SetDepth(float depth);	void ZBuffer_Invert();	void ZBuffer_Flip();...


As you can see, this class just needs to manipulate the APIShaderObject interface, and perhaps do some error checking or logging. There's just a lot of functions dealing with a small amount of data.

As an example of how prefixing can help organize a mass of interface functions, let's look at the IDirect3DDevice9 interface..
BeginSceneBeginStateBlockClearColorFillCreateAdditionalSwapChainCreateCubeTextureCreateDepthStencilSurfaceCreateIndexBufferCreateOffscreenPlainSurfaceCreatePixelShaderCreateQueryCreateRenderTargetCreateStateBlockCreateTextureCreateVertexBufferCreateVertexDeclarationCreateVertexShaderCreateVolumeTextureDeletePatchDrawIndexedPrimitiveDrawIndexedPrimitiveUPDrawPrimitiveDrawPrimitiveUPDrawRectPatchDrawTriPatchEndSceneEndStateBlockEvictManagedResourcesGetAvailableTextureMemGetBackBufferGetClipPlaneGetClipStatusGetCreationParametersGetCurrentTexturePaletteGetDepthStencilSurfaceGetDeviceCapsGetDirect3DGetDisplayModeGetFrontBufferDataGetFVFGetGammaRampGetIndicesGetLightGetLightEnableGetMaterialGetNPatchModeGetNumberOfSwapChainsGetPaletteEntriesGetPixelShaderGetPixelShaderConstantBGetPixelShaderConstantFGetPixelShaderConstantIGetRasterStatusGetRenderStateGetRenderTargetGetRenderTargetDataGetSamplerStateGetScissorRectGetSoftwareVertexProcessingGetStreamSourceGetStreamSourceFreqGetSwapChainGetTextureGetTextureStageStateGetTransformGetVertexDeclarationGetVertexShaderGetVertexShaderConstantBGetVertexShaderConstantFGetVertexShaderConstantIGetViewportLightEnableMultiplyTransformPresentProcessVerticesResetSetClipPlaneSetClipStatusSetCurrentTexturePaletteSetCursorPositionSetCursorPropertiesSetDepthStencilSurfaceSetDialogBoxModeSetFVFSetGammaRampSetIndicesSetLightSetMaterialSetNPatchModeSetPaletteEntriesSetPixelShaderSetPixelShaderConstantBSetPixelShaderConstantFSetPixelShaderConstantISetRenderStateSetRenderTargetSetSamplerStateSetScissorRectSetSoftwareVertexProcessingSetStreamSourceSetStreamSourceFreqSetTextureSetTextureStageStateSetTransformSetVertexDeclarationSetVertexShaderSetVertexShaderConstantBSetVertexShaderConstantFSetVertexShaderConstantISetViewportShowCursorStretchRectTestCooperativeLevelUpdateSurfaceUpdateTextureValidateDevice

A lot of functions dealing with render states. Quite a few pixel shaders, and vertex shaders. Stream sources, textures, and specific buffers. Good luck trying to sort it out as you code. You need a reference for this.

I also do not like jumping to header files every time I need to access a specific object or perform a specific task. I just like to use the IDE tools to speed the process up. With this type of setup, that's not even a question to be considered.
Advertisement
Well I'm pretty much out of ideas with regards to directly emulating namespaces.

As for the MegaBadDesign example, I'd deal with that by seperating it out into subclasses (honest to gosh seperate ones). It does require a decent bit of support framework, but that's just typing, and at my ~80WPM I spend much more time thinking about my design(s) than I spend typing.
As the OP has designed his system, all these responsibilities belong to this class, so there's no point hacking around trying to seperate them into different classes from the few scraps of the design we've been given. Doing this properly would require redefining what the class itself is, so it doesn't have all these responsibilities to begin with. Right now it is aware of every operation that has to be performed on it. Changing this requires changing the way in which these operations are performed, and hence the way in which all other classes which are aware of it interact with it, which looks like it'll be pretty much everything (which is one of the problems of low cohesion incidentally).
Your solution is as good as it gets, as far as I can imagine. I just think the change is really big compared to the goal.

I totally agree that dividing the tasks up is a great way to simplify and organize. But in my case, it's just the function list that I want to divide. I don't want seperate objects.

For what it's worth, I didn't really expect anyone to invent a solution to the problem. I was just curious to know if there was already such a thing being used.

edit @ Nemesis2k2: What you see is what you get. There's no hidden part of the design that's going to change your perspective. Compare it to the Direct3D device. It's an object (a human being) who has a lot of branches in functionality. It already contains a lot of classes seperating that functionality. But so does the Direct3D device. Yet, look at it's interface. I would hate to see it's private task list, as that is what is huge on my character class.
Quote:edit @ Nemesis2k2: What you see is what you get. There's no hidden part of the design that's going to change your perspective. Compare it to the Direct3D device. It's an object (a human being) who has a lot of branches in functionality. It already contains a lot of classes seperating that functionality. But so does the Direct3D device. Yet, look at it's interface. I would hate to see it's private task list, as that is what is huge on my character class.

There is still a lot of vital documentation to understanding the overall design of your system that is not in this thread, but at any rate, there are many different ways to design a system to solve a given problem, especially one as complex as this. For example, my engine has a Renderer base class, through which any portion of the scene can be rendered. The Renderer itself currently has only 5 functions in its public interface, and as the system has been designed, that is sufficient in order to:

-Assign a rendering target
-Sort all renderable assets
-Mask out "categories" of renderable assets (categories are used to classify resources, to allow discriminate rendering, such as not rendering reflections within reflections, using lower detail objects for a perticular view, etc etc)
-Generate any volatile resources that must be created first. Eg, a reflection texture.
-Lock certain material states to specified values (eg, force everything to render in wireframe)
-Render the scene on demand; either selected portions or in its entirety
-Clear the list of assets to be rendered, in order to reuse the object for another rendering task

Achieving such low coupling however requires first of all aiming for it as a design objective, and it needs to be pervasive throughout the architecture of your system. IMO, it is something worth aiming for. The end result is easier to understand for people using your system, it's easier to maintain, and it's more resiliant to future changes. Build your systems however you like of course, but I do recommend when you approach systems in the future, you think of ways to minimize coupling from the outset. Just some constructive feedback.
In general, I use a lot of functions. I seperate medium tasks into several smaller tasks. I find it much easier to flow through code this way. The public interface of my character class is virtually non-existent. It's derived from a map based object class, and most of the game engine doesn't even interact specifically with characters (small exceptions, like menu routines working with inventory lists). It's the private section that is complex. The number of data members is lower than ten, but the number of functions in the private area is mega huge. This is the problem area. The inner functionality of my characters is becoming very complex.

I might be way off, but I don't see how low coupling strategy is going to help. The private tasks all work with the same small amount of data. They just do a very wide range of things with it. They are coupled in their origin, not by design.
It sounds like the best solution in C++ would be to create friend classes that only contain methods and are passed a pointer to the master character class.

This topic is closed to new replies.

Advertisement