编写可维护的代码 (二)

本贴最后更新于 2637 天前,其中的信息可能已经时异事殊

假如一个系统中有多个模块,不妨命名为 Module1, Module2, Module3......, 毫无疑问这个系统的启动过程中需要初始化所有这些模块, 而退出时要销毁它们, 那应该用下面哪种方法来完成这个任务呢?

A. 让这些模块都支持一个 IModule, 然后定义一个 IModule*类型的数组, 把这些模块的指针都加进去:

IModule* modules[] = {&Module1, &Module2, &Module3, ...}; // 初始化时: for(int i = 0; i < sizeof(modules)/sizeof(modules[0]); ++i) modules[i]->Init(); // 退出时: for(int i = sizeof(modules)/sizeof(modules[0]) - 1; i >= 0; --i) modules[i]->Uninit();

B. 老老实实的一个一个的来:

// 初始化时: Module1.Init(); Module2.Init(); Module3.Init(); ... // 退出时: ... Module3.Uninit(); Module2.Uninit(); Module1.Uninit();

如果你读了我的上一篇, 你肯定能猜到我的选择是 B. 但我想先说说 A, 把 A 说清楚了, 选择 B 的理由也就出来了。

A 是典型的数据驱动 + Builder 模式, 它最大的优点是增加或删除一个模块只需要增加或删除一个数据项, 耦合很小, 所以看起来非常优雅。

而 A 的缺点有两个. 和上一篇一样, 其中之一也出在调试上: 当一个模块初始化失败后, 如果我们只看外面这些代码, 没有办法一眼得出是谁失败了, 必须得多一些操作才行。

第二点是 A 实现强制了模块的初始化和退出顺序, 先初始化的模块后退出貌似很合理, 但在一个大型系统中却总会出例外, 而且还可能出现 Module1 先初始化一半, 然后 Module2 初始化, 之后 Module1 再继续初始化等情况. 当然, 我们可以使用"把初始化顺序和退出顺序定义在两个数组中"或"把初始化划分为多个阶段"等方法处理这些问题, 但这些方法都会增加复杂性, 而且也都不能从根本上解决问题。

B 实现则用简单直接的方法很好的避免了 A 的问题, 虽然它看起来好像很笨, 增加删除一个模块要改多个地方, 但这些改动总共也不过几行代码, 而且往往只涉及一个文件, 所以总体代价并不高。

最后, 本文的场景乍看起来非常适合使用 Builder 模式, 可为什么使用它的效果不好呢? 我本人对设计模式不感冒也不擅长, 所以只能试着解释一下这个问题:其原因就是这个场景只是看起来像, 但其实并不适用 Builder 模式. Builder 模式要求对象支持统一的接口, 也希望对象之间没什么关联, 这是我们作设计时追求的目标, 但在实现一个复杂系统时却很难完全满足这些要求, 所以硬套上去就会出问题。而且在实现一个系统时, 各个模块还不可能完全定下来, 实现过程中的改动也会给 Buidler 模式带来麻烦。按我个人的理解, Buidler 模式不应被用来处理系统的主体模块, 它真正的适用场合之一是实现对插件的支持, 把所有插件定义在一个列表中, 然后逐项处理, 因为这时系统的主体功能已经完成, 所以可以为插件定义出清晰的接口, 而且就算定义的接口有一点问题, 它所影响的也只是某些插件而非主体功能了。

  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3455 回帖 • 153 关注
  • 技术

    到底什么才是技术呢?

    88 引用 • 179 回帖 • 4 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...

推荐标签 标签

  • Vue.js

    Vue.js(读音 /vju ː/,类似于 view)是一个构建数据驱动的 Web 界面库。Vue.js 的目标是通过尽可能简单的 API 实现响应的数据绑定和组合的视图组件。

    268 引用 • 666 回帖 • 1 关注
  • Flume

    Flume 是一套分布式的、可靠的,可用于有效地收集、聚合和搬运大量日志数据的服务架构。

    9 引用 • 6 回帖 • 661 关注
  • Scala

    Scala 是一门多范式的编程语言,集成面向对象编程和函数式编程的各种特性。

    13 引用 • 11 回帖 • 156 关注
  • TGIF

    Thank God It's Friday! 感谢老天,总算到星期五啦!

    291 引用 • 4495 回帖 • 661 关注
  • 黑曜石

    黑曜石是一款强大的知识库工具,支持本地 Markdown 文件编辑,支持双向链接和关系图。

    A second brain, for you, forever.

    24 引用 • 242 回帖 • 1 关注
  • Elasticsearch

    Elasticsearch 是一个基于 Lucene 的搜索服务器。它提供了一个分布式多用户能力的全文搜索引擎,基于 RESTful 接口。Elasticsearch 是用 Java 开发的,并作为 Apache 许可条款下的开放源码发布,是当前流行的企业级搜索引擎。设计用于云计算中,能够达到实时搜索,稳定,可靠,快速,安装使用方便。

    117 引用 • 99 回帖 • 195 关注
  • Love2D

    Love2D 是一个开源的, 跨平台的 2D 游戏引擎。使用纯 Lua 脚本来进行游戏开发。目前支持的平台有 Windows, Mac OS X, Linux, Android 和 iOS。

    14 引用 • 53 回帖 • 558 关注
  • sts
    2 引用 • 2 回帖 • 241 关注
  • WebSocket

    WebSocket 是 HTML5 中定义的一种新协议,它实现了浏览器与服务器之间的全双工通信(full-duplex)。

    48 引用 • 206 回帖 • 287 关注
  • AngularJS

    AngularJS 诞生于 2009 年,由 Misko Hevery 等人创建,后为 Google 所收购。是一款优秀的前端 JS 框架,已经被用于 Google 的多款产品当中。AngularJS 有着诸多特性,最为核心的是:MVC、模块化、自动化双向数据绑定、语义化标签、依赖注入等。2.0 版本后已经改名为 Angular。

    12 引用 • 50 回帖 • 512 关注
  • Gitea

    Gitea 是一个开源社区驱动的轻量级代码托管解决方案,后端采用 Go 编写,采用 MIT 许可证。

    5 引用 • 16 回帖 • 2 关注
  • SVN

    SVN 是 Subversion 的简称,是一个开放源代码的版本控制系统,相较于 RCS、CVS,它采用了分支管理系统,它的设计目标就是取代 CVS。

    29 引用 • 98 回帖 • 694 关注
  • SendCloud

    SendCloud 由搜狐武汉研发中心孵化的项目,是致力于为开发者提供高质量的触发邮件服务的云端邮件发送平台,为开发者提供便利的 API 接口来调用服务,让邮件准确迅速到达用户收件箱并获得强大的追踪数据。

    2 引用 • 8 回帖 • 502 关注
  • 前端

    前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

    246 引用 • 1338 回帖 • 2 关注
  • PWA

    PWA(Progressive Web App)是 Google 在 2015 年提出、2016 年 6 月开始推广的项目。它结合了一系列现代 Web 技术,在网页应用中实现和原生应用相近的用户体验。

    14 引用 • 69 回帖 • 184 关注
  • B3log

    B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:SymSoloVditor思源笔记

    1063 引用 • 3455 回帖 • 153 关注
  • Oracle

    Oracle(甲骨文)公司,全称甲骨文股份有限公司(甲骨文软件系统有限公司),是全球最大的企业级软件公司,总部位于美国加利福尼亚州的红木滩。1989 年正式进入中国市场。2013 年,甲骨文已超越 IBM,成为继 Microsoft 后全球第二大软件公司。

    107 引用 • 127 回帖 • 342 关注
  • 安装

    你若安好,便是晴天。

    132 引用 • 1184 回帖 • 1 关注
  • 小薇

    小薇是一个用 Java 写的 QQ 聊天机器人 Web 服务,可以用于社群互动。

    由于 Smart QQ 从 2019 年 1 月 1 日起停止服务,所以该项目也已经停止维护了!

    35 引用 • 468 回帖 • 762 关注
  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    108 引用 • 153 回帖
  • Laravel

    Laravel 是一套简洁、优雅的 PHP Web 开发框架。它采用 MVC 设计,是一款崇尚开发效率的全栈框架。

    19 引用 • 23 回帖 • 737 关注
  • 房星科技

    房星网,我们不和没有钱的程序员谈理想,我们要让程序员又有理想又有钱。我们有雄厚的房地产行业线下资源,遍布昆明全城的 100 家门店、四千地产经纪人是我们坚实的后盾。

    6 引用 • 141 回帖 • 603 关注
  • Swagger

    Swagger 是一款非常流行的 API 开发工具,它遵循 OpenAPI Specification(这是一种通用的、和编程语言无关的 API 描述规范)。Swagger 贯穿整个 API 生命周期,如 API 的设计、编写文档、测试和部署。

    26 引用 • 35 回帖 • 5 关注
  • 周末

    星期六到星期天晚,实行五天工作制后,指每周的最后两天。再过几年可能就是三天了。

    14 引用 • 297 回帖 • 2 关注
  • Caddy

    Caddy 是一款默认自动启用 HTTPS 的 HTTP/2 Web 服务器。

    10 引用 • 54 回帖 • 176 关注
  • 博客

    记录并分享人生的经历。

    273 引用 • 2388 回帖 • 1 关注
  • 国际化

    i18n(其来源是英文单词 internationalization 的首末字符 i 和 n,18 为中间的字符数)是“国际化”的简称。对程序来说,国际化是指在不修改代码的情况下,能根据不同语言及地区显示相应的界面。

    8 引用 • 26 回帖 • 2 关注