【问题标题】:How to organize code well in root class?如何在根类中组织好代码?
【发布时间】:2013-09-15 21:22:33
【问题描述】:

所以,我用 C++ 编写这个软件已经有一段时间了。它有 gui 并且 gui 可以访问主类对象,该对象负责 gui 所做的任何任务(当用户单击某些东西时,gui 只是调用该对象的方法)。

现在,我不知道这是否是最好的方法。我一生中从未在任何编码公司工作过,但我遇到了一些问题。

实际上,大师班并没有做任何事情。它主要是位于该类中的其他对象的包装器。所以,例如:

class Master {
public:
    void writeSomethingToFile(const char *filename,std::string& text);
...
}

幕后:

class Master {
...
private:
    FileWriter *_writer;
}

void Master::writeSomethingToFile(const char *filename,std::string& text) {
    _writer->write(filename,text);
}

所以,大师班自己不写,它只是把任务交给作家班应该做的工作。

master 类有很多对象,比如 writer 类,所以,就 gui 而言,master 类可以满足它在程序中需要的任何东西。

然而,master 类中的代码 get 有点笨拙,因为它包含所有这些包装器方法,它有很多方法。

由于它使用所有这些其他类,所以每当我更改使用的类主类的任何头文件时,也必须重新编译 .cpp 文件(对于 i7 处理器来说还不错,但我宁愿避免使用它)。

我现在使用的东西很原始,我绝不会这样辩护:

class Master {
public:
    // FILE CHANNEL
    void writeToFile(...);
    void deleteFile(...);
    // FILE CHANNEL

    // ARITHMETIC CHANNEL
    void addNumbers(...);
    void multiplyNumbers(...);
    // ARITHMETIC CHANNEL

    ...
}

我会从字面上将我称之为“通道”的东西与 cmets 分开,这样我就可以理解什么属于什么。现在,对于 gui 来说,这可能不是那么糟糕,因为所有内容都是分组的。然而,当我进一步开发这个类时,向它添加新的内部类并包装更多方法时,东西变得笨重,最困扰我的是,它不是坚如磐石。我的意思是,如果我从评论的“频道”中采用一种方法并将其放入另一种方法中,我真的会看到区别吗?

我想到了几个解决方案。我从未尝试过,但我可以创建成员空间:

class Master {
public:
    namespace file {
        void writeToFile(...);
        void deleteFile(...);
    }

    namespace arithmetic {
        void addNumbers(...);
        void multiplyNumbers(...);
    }

    ...
}

这解决了我作为类开发人员的问题,但是,对于 gui,他们现在必须调用类似

的方法
master->arithmetic.addNumbers(...); // My syntax could be wrong here
// never used memberspace, corrections are appreciated

现在,由于我的项目目前“有点”摇摆不定,这意味着要修改很多代码。

我想到的另一个解决方案是从一个类到另一个类的持续继承,其中文件中的主类专注于一个通道:

class Master_fileChannel {
     FileHandler *_fileHandler;
     void writeToFile(...);
     void deleteFile(...);
}

...

class Master_arithmeticChannel : public Master_fileChannel {
     ArithmeticUnit *_arithmeticUnit;
     void addNumbers(...);
     void multiplyNumbers(...);
}

以此类推,直到我继承每个“频道”。这将比原始状态更稳固,并使文件比此类的当前 .cpp 文件短很多。但是,我仍然会遇到问题,我可能会使用重复的方法名称,并且必须为我的方法编造越来越多的笨拙名称(即 addNumbers(..); addThreadNumbers(..); addThreadNumbersSeparately(..);

那么,你建议我在这里做什么?我可以将那个大师班建立到无限,但我相信有更好的方法。在真正大小合适的代码库中如何处理这些事情?我能否在所有项目中快速重构代码以不费吹灰之力地完成这些重大更改?

【问题讨论】:

标签: c++ code-organization


【解决方案1】:

正如@Mat 在 cmets 中提到的那样,您发现自己伴随着所谓的“上帝对象”——它管理您项目中的每一件事,任何代码更改都会影响这个“上帝”。

只要您有一些开发经验,就值得阅读一些最佳实践:

【讨论】:

  • 我打开了那本书,它大约有 400 页。难道没有任何精确的解决方案可以针对我的情况专门拆分我的上帝对象吗?
  • @VanillaFace:没有单一的解决方案正是因为上帝对象做了很多事情。每一个都可能需要不同的修复。
  • 但是如果我在上帝对象中有不同的对象,这些对象是完全独立的,并且没有一个内部对象知道上帝对象实际上存在,我应该简单地给GUI一个指向这些对象的指针吗?因为应用程序是多线程的,所以我发现当我将互斥锁放入包装器时防止上帝对象中的错误非常方便,因此内部对象可能不是线程安全的,但上帝对象确保它们是线程安全的。如果我将任务对象的指针指向 GUI,一切都可以自行运行,那么每个对象都必须是线程安全的。 95% 的互斥锁在上帝对象中。更具体吗?
  • @VanillaFace,你不需要从头到尾阅读这本书——它会在阅读 3-4 个模式后调整你的想法。然后,简要介绍 MVC 和 MVVM 方法,因为它们准确地解决了“如何拆分 UI 和逻辑”,包括多线程环境。
【解决方案2】:

在这种情况下,修复看起来相当简单。只需放弃整个大师班。它不会增加任何价值,因此保留它没有任何好处。

您的FILE CHANNELnamespace file 已经存在,并且被称为class FileWriter

我对@9​​87654324@ 的说法有点怀疑。这可能不应该出现在 write 方法中,应该传递给 FileWriter 构造函数。每个文件都应该有自己的编写器。

【讨论】:

  • 不,我在这里写的方法纯属推测,它们不是代码的一部分。事实上,我有文件管理器类,是的,它在构造函数中接收文件名。在第一部分,当我放弃大师班时,谁控制逻辑?那么 GUI 是否应该直接从负责任务的对象中直接调用方法?我应该把所有的物品放在哪里?大师班及其对象只创建一次,我不想在堆上分配新空间。我是否应该创建一个容器类/结构,除了保存所有这些对象之外什么都不做?
猜你喜欢
  • 1970-01-01
  • 2011-08-08
  • 2023-03-24
  • 1970-01-01
  • 1970-01-01
  • 2020-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多