怎样设计好一个C++程序里面的模块

怎样设计好一个C++程序里面的模块,需要考虑哪些因素,比如:兼容性、可移植等等,
有没有什么好的理论思想、书籍推荐,有哪些可以参考的设计模式,比如:模块的接口可以使用 门面模式来统一入口,其它还有什么呢?

关于第一个问题,其实考虑的不仅仅是兼容性,还需要考虑高可用,灾难可恢复等因素
比如关于性能上:
在多线程环境里,需要明确提供给上层的方法是否线程安全,如果不是线程安全的,在上层应用使用的时候加锁是否影响当前的性能。
在要求快速相应的模块里,需要考虑当前的接口是否可以快速相应,那么需要考虑是否使用缓存来快速查询,而不是从数据库或文件的方式来异步加载返回。
比如关于高可用:
现在讲究的是系统需要高可用,当其中几台服务器宕机或异常崩溃,需要保障当前业务服务仍然能正常运行,而且不影响业务的继续执行,所以需要在系统设计的时候就要考虑,所以在一般业务进行中会在缓存或者数据库里保存重要的业务运行时的快照(比如业务执行到哪一步,当前都有哪些重要的临时数据放到缓存或者数据库里),一旦发生崩溃宕机,我们需要在拉起重启的时候从当时运行时环境的缓存信息(一般重要数据缓存起来)里恢复当时的运行时环境,重新跑, 如果当前服务没有重启,由其中一个管理服务分配到集群内的其他服务器来托管继续运行,确保崩溃的事故对用户无感知。
比如最实际的可扩展性和可读性:
这个建议看看谷歌编码规范,不同语言由不同语言的编码规范,多看看开源代码,对于函数的参数不能过多,一个函数最好不要做太多复杂的逻辑,尽可能的降低和其他模块的耦合性,比如你要实现一个查找一个业务数据,然后做处理,再排序, 最好不要放到一个函数里,否则你的需求后期变更,你的逻辑将越来越复杂,可以将查询,做处理,排序的逻辑分开。
可移植性:
这个基本上都是用宏来控制


        SOCK_Stream *stream = new SOCK_Stream(new_id, m_net_manager, m_packet_splitter, accept_socket, m_local_addr, remote_addr, m_UserData);
        
        //rc = reactor()->register_handler(stream, MASK_READ | MASK_WRITE);
#ifdef WIN32
        rc = reactor()->register_handler(stream, MASK_READ | MASK_WRITE);
#else
        rc = reactor()->register_handler(stream, MASK_READ);
#endif
        if (0 != rc) {
            LOG(ERROR)("SOCK_Acceptor::handle_input error, register_handler MASK_READ error");
            stream->close_stream();
            delete stream;
            return 0;
        }


然后在各个不同平台来实现对应的平台相关调用。
关于第二个问题:
建议多看看设计模式:比如常见的桥接模式,单例,工厂模式,代理,适配器,观察者模式等。
推荐看看 大话设计模式 ,或者我的博客,了解更多游戏服务器架构设计

参考GPT:设计一个好的C++程序模块需要考虑以下因素:

1 可重用性:模块应该是可重用的,可以在不同的项目中使用。为了达到这个目的,可以尽量减少与其他模块的依赖,减少对特定环境的依赖。

2 可维护性:模块应该易于维护和修改。这就要求代码要清晰易读,命名要规范,注释要详细。

3 可扩展性:模块应该能够很容易地扩展。当需求改变时,模块能够适应新的需求,而不需要大规模修改代码。

4 可测试性:模块应该易于测试。测试是确保代码质量的重要手段,应该设计模块,使得测试代码的编写变得容易。
5 可移植性:模块应该易于移植。为了使模块能够运行在不同的平台上,应该减少与特定平台相关的代码。

在设计模块时,可以参考以下设计模式:
1 门面模式:将模块的接口封装到一个门面类中,以统一接口,降低其他模块与该模块的耦合度。

2 单例模式:确保模块在程序运行期间只有一个实例。

3 工厂模式:用工厂类来创建模块实例,这样可以将模块的创建和使用分离开来。

4 观察者模式:当模块的状态改变时,观察者可以得到通知。
5 责任链模式:多个模块按照一定的顺序处理同一个请求,直到请求被处理为止。

关于C++模块设计,推荐以下书籍:

1.《C++设计模式与实践》(Modern C++ Design: Generic Programming and Design Patterns Applied),作者Andrei Alexandrescu。

2.《大话设计模式》(Head First Design Patterns),作者Eric Freeman等。

3.《C++编程规范》(C++ Coding Standards: 101 Rules, Guidelines, and Best Practices),作者Herb Sutter和Andrei Alexandrescu。
4.《高质量C++编程指南》(Effective C++: 55 Specific Ways to Improve Your Programs and Designs),作者Scott Meyers。

总之,在设计C++程序模块时,要注重代码的可重用性、可维护性、可扩展性、可测试性和可移植性。同时,可以借鉴设计模式来提高代码的质量和可维护性。

当设计C++程序的模块时,需要考虑以下因素:

  1. 兼容性,即程序能够在不同的操作系统上运行,并且用户可以在不同的编译器和平台上使用它。

  2. 可移植性,即程序能在不同的环境和设备上运行,因此需要确保代码的可移植性和可重用性。

  3. 可维护性,即程序在未来可以被修改和扩展。

  4. 可测试性,即程序的模块应该可以独立地进行单元测试。

  5. 可读性,即模块应该被设计得易于阅读和理解。

对于好的理论思想和书籍推荐,这里给几个建议:

  1. 设计模式:可参考设计模式的相关书籍,比如《设计模式:可复用面向对象软件的基础》。

  2. SOLID 原则:这是一组面向对象编程的原则,可将其用于模块设计中,包括单一职责原则、开闭原则、里氏替换原则、接口隔离原则和依赖反转原则。

  3. Clean Code:适用于任何编程语言和项目的一系列建议和实践,其中包括模块设计的最佳实践。

对于模块接口的设计模式,除了门面模式,还有以下几种:

  1. 适配器模式:将一个类的接口转换为另一个接口,以满足客户的需求。

  2. 提供者模式:定义一种方式,使得一个或多个对象将负责创建或提供另一个对象的实例。

  3. 策略模式:定义一系列算法,将每个算法封装在独立的类中,并使它们可以相互替换。

总之,在进行模块设计时,要考虑可维护性、可测试性、可读性和可移植性等因素,利用设计模式和最佳实践进行模块设计和接口设计,以实现良好的代码质量和可重用性。
除了上文提到的门面模式、适配器模式、提供者模式和策略模式外,还有一些其他的设计模式可以用于模块设计。下面列出了一些常见的设计模式:

  1. 工厂模式:使用工厂方法或抽象工厂来封装对象的创建过程。

  2. 观察者模式:定义一对多的依赖关系,当一个对象发生改变时,所有依赖它的对象都会被通知并自动更新。

  3. 单例模式:保证一个类仅有一个实例,并提供一个全局访问点。

  4. 装饰器模式:动态地将责任附加到对象上,以扩展其功能。

  5. 组合模式:将对象组合成树形结构来表示"部分-整体"的层次结构,使得客户端可以统一对待单个对象和组合对象。

  6. 外观模式:提供一个简单的接口,隐藏子系统的复杂性。

在模块设计中,需要根据实际情况选择合适的模式,并根据模式的原则来实现模块之间的协作和通信。同时,要善于封装和隐藏模块内部的实现细节,以提高代码的可维护性和可扩展性。
除了上文提到的门面模式、适配器模式、提供者模式和策略模式外,还有一些其他的设计模式可以用于模块设计。下面列出了一些常见的设计模式:

  1. 工厂模式:使用工厂方法或抽象工厂来封装对象的创建过程。

  2. 观察者模式:定义一对多的依赖关系,当一个对象发生改变时,所有依赖它的对象都会被通知并自动更新。

  3. 单例模式:保证一个类仅有一个实例,并提供一个全局访问点。

  4. 装饰器模式:动态地将责任附加到对象上,以扩展其功能。

  5. 组合模式:将对象组合成树形结构来表示"部分-整体"的层次结构,使得客户端可以统一对待单个对象和组合对象。

  6. 外观模式:提供一个简单的接口,隐藏子系统的复杂性。

在模块设计中,需要根据实际情况选择合适的模式,并根据模式的原则来实现模块之间的协作和通信。同时,要善于封装和隐藏模块内部的实现细节,以提高代码的可维护性和可扩展性。