我正在试图弄清楚我是否正确理解了模块化代码的真正含义。我知道它非常强大/有用,所以我想确保我正确地学习它。
为了开始学习,我制作了一个相当简单的系统,根据一些标准将实体组合在一起。先到先得。
我还想以图形方式显示群组及其成员,以向用户(我自己)显示正在发生的事情。我将使用SDL库。
所以让我们把它分成几个类;
实体
主类“实体”将具有用于线程安全的Boost :: mutex,以及包含指向实际实体的指针的映射。当提供实体ID时,让我们创建一个从所述映射中检索指向实际实体的指针的函数。
class Entities
{
public:
boost::mutex access_entitymap; //Thread safety
std::map<unsigned int, Entity*> entitymap;
Entity* getEntity(unsigned int entityID);
};
实体
保存有关实际实体的信息,例如它的唯一ID。并指向父“实体”的指针。
LFDGroups
分组系统。
包含指向实际组的指针的地图,
具有组在队列中的位置的地图(先到先服务。从该地图中删除完整的组以使迭代更快),
和一个实体在该组中的位置的地图(5个点,哪个实体占据了哪个点?)。
此外,它还包括一些在所述地图上操作的功能。如添加和删除成员。作为示例,addmember()
函数将确保将实体添加到具有最高优先级的组中,或者在必要时创建新组。
groupObject
保存有关实际组的信息,例如它的唯一ID和它的居民实体ID。但也有一些功能,如;
LFDGroups *lfdgroup; //Parent LFDGroups;
bool isEmpty(); //is this group empty?
bool isFull(); //is this group full?
unsigned int getPosition(); //Position in queue?
bool addMember(unsigned int entityID,bool snatchIt);
/*Add a member. Calls removeMember() on the entities' groupObject
first if the entityID is already in another group.*/
bool removeMember(unsigned int entityID,bool snatchIt);
/*Remove a member from this group, and snatch a member from another
group further up in the queue. This ensures groups are always full
if enough people are queued.*/
bool hasMember(unsigned int entityID); //Is this entity ID in our group?
/*etc. etc.*/
队列
提供一些易于使用的功能,使测试更容易。如;
void addFakeEntity(bool queuenow); //Create an all new entity and immediately queue it.
void removeFakeEntity(); //Remove a random entity from a random group
void removeFakeEntity(unsigned int entityID); //Remove a given entity from it's corresponding group.
SDLMain
以图形方式显示LFDGroups组的内容。它有多少成员,哪些斑点被采取,哪些不是等等。
还证明按钮可以使用Queue的功能。例如“添加”按钮将调用“queue-&gt; addFakeEntity(true)”
所以现在我可以轻松地开始整个事情;
#include "SDL_main.h" //gfx
#include "class_LFDGroups.h" //group system
#include "queue.h" //ease of use for testing
#include "class_entities.h" //entities
int main( int argc, char* args[] )
{
Entities * entities = new Entities;
LFDGroups * lfdgroups = new LFDGroups(entities);
Queue * queue = new Queue(lfdgroups);
SDLMain * sdlmain = new SDLMain(queue);
return 1;
}
果然;
所以这意味着即使我禁用图形显示组,我仍然可以将实际的分组系统用于其他事情。
而且,与某些对象相关的功能也在该对象本身内。例如,Entity* getEntity(unsigned int entityID);
函数位于Entities
类中,而不在groupObject
中,即使这是目前唯一正在使用它的函数。
这就是模块化编码吗?我做得对吗?
答案 0 :(得分:2)
是的,您的程序希望遵循模块化编程范例,例如将各个组件组合在一起组成程序,并以特定组件可替换的方式编写。
因此,您已将程序的逻辑拆分为单独的类,并且还将类拆分为单独的编译单元(假设如此,基于SDLMain.h源中的包含),因此要添加新功能说你的小组类,只需要改变那个模块(假设新的功能只在内部被那个类调用),并且通过查看你的来源,程序在逻辑上被分成易于识别的独立部分。
您也可以轻松替换部分代码,例如,GUI前端可以替换为Qt或wxwindows。由于gui调用数据的操作不会改变,因此可以编写新的gui代码,并调用同一组操作,并且不的数据组件将被更改。