【大型软件开发】浅谈大型Qt软件开发(二)面向未来开发——来自未来的技术:COM组件。我如何做到让我们的教学模块像插件一样即插即用,以及为什么这么做。
前言
最近我们项目部的核心产品正在进行重构,然后又是年底了,除了开发工作之外项目并不紧急,加上加班时间混不够了....所以就忙里偷闲把整个项目的开发思路聊一下,以供参考。
鉴于接下来的一年我要进行这个主框架的开发,本着精益求精的态度,加上之前维护前辈的产品代码确实给我这个刚毕业的社畜带来了不小的震撼,我决定在这个模块的开发中优化之前的开发模式,提升整个产品的健壮性和独立性。
开发一个大型软件最重要的问题有三个,一是如何保证每个模块开发的独立性 二是如何保证数据结构的一致性 三是如何保证程序的可维护性和健壮性。这几个文章的内容我会在几篇文章中分开聊聊我的做法,做个记录。
本篇文章聊聊如何保证各个模块开发的独立性——怎么让功能模块、教学模块的开发独立于主框架本身。让不同的模块之间尽量通过接口的形式进行交互,而抛弃传统的中转消息码->调用模块的模式,让实际功能以接口形式暴露。
这一期简单聊聊开发准备,下一期浅谈怎么在开发中我们项目如何保证模块开发的独立性。
技术背景
请在阅读以下两篇文章之后观看本文以获得更佳的体验,以免你不知道我在说什么。
Qt开发Active控件:如何使用ActiveQt Server开发大型软件的主框架
【大型软件开发】浅谈大型Qt软件开发(一)开发前的准备——在着手开发之前,我们要做些什么?
为什么?
我们谈到为什么要这样开发的之前,要先聊聊之前我们的框架。
我们的软件之前没有框架,就是一个大的C#程序,然后里面想到什么就塞什么,然后教学模块、主框架、功能模块之间就通过一个C#事件委托向上传递。教学模块中没有办法直接引用所有的功能模块,而是通过一个函数里面传参,再转移到主程序中去。
这个模式本身是没有任何问题的,但是也可能是开发人员当时在开发的时候没有考虑过这个项目要维护十多年,导致整个程序在后面变成了一个几乎不可维护的庞然大物。
这里功能模块是几乎嵌死在主框架内的,这个是可以的,因为功能模块一般是调用外部的DLL或者对外部exe的管理,一般会和这些模块之间有深度的交互。而且一般我们也很少更新新的功能模块,光是现有的功能模块就几乎够了,之后的更新哪怕是直接嵌入在主框架内也是没有关系的。
当然了,功能模块也是一个个DLL,但是原先的调用是在使用的时候去尝试实例化一个功能类,然后再调用其中的方法。这样就涉及到调用、事件绑定等问题。
最严重的问题还是来自教学模块的信息向上传递。这个是由于引用导致的:
1.我们不可能让每个教学模块去引用各个功能模块,这样主框架完全脱离了教学模块的掌控,那相当于是每个教学模块重新开发了。而且每个功能模块并不能直接这样使用,需要的很多参数和消息都必须在主框架中获取或者初始化。比如座位信息,我们这个产品有一套很复杂的座位信息数据。还有一些比如MAC地址等。如果独立获取会极大的提升整个产品开发的维护难度和开发难度。
2.只能由框架去调用教学模块,这也就导致消息没法直接向上传递,只能通过类似回调函数的事件委托将事件以类似 key-value键值对的形式向上发送。这样我的主框架就要写一大堆if else去根据每个key去判断教学模块发这个消息想表达什么了。
我这里展示其中一部分就知道有多逆天了:
当然就像我说的,这是由于早期设计的时候完全没有考虑程序的拓展性开发所用的妥协性开发策略。在一开始确实方便而且好用。在后面这样一大坨if else让整个代码维护起来简直异常困难,更别提在接到消息之后这里还需要小小处理一下。
3.教学模块没法独立开发,必须依托于教师端。怎么说呢,就是教学模块几乎完全没法脱离教师端进行开发,因为要教学模块也需要暴露一大堆方法和接口供主框架去交互。模块设计操作起来就非常恶心了。
甚至!我们之前有过用exe的应用程序,所有的信息交互都是通过SendMessage进行的!你知道那对我幼小的心灵造成了多么大的伤害吗!这样的教学模块几乎是完完全全嵌在主框架内的专用exe,几乎不存在什么扩展性和维护性,因为除了问题除了开发者本人,别人根本没法改,也不知道怎么改。
或者我们换一种说法:教学模块这样设计就只能让主框架开发人员开发,且很难多个模块之间平行开发。
怎么做?
这就不得不提到面向未来的技术:COM组件
COM组件可以让主框架提供接口,然后各个教学模块就可以直接去调用主框架提供的接口。这样就直接替换掉了我上面说的if else判定这种僵硬的开发方式。
这个是ActiveQt Server向外公布的接口文档
这里提供的Public slots 就是主框架提供的方法。这样我们就可以通过直接调用接口的方式调用主框架内部的服务了。
也就是说框架实际上和之前的那个if else也差不多,区别就是主框架不需要在接收到消息之后进行检索,可以直接调用接口了。也就是说不需要维护那么长一条if else 链,而是暴露接口,管理接口即可~
就这样?当然不止,在这里我还提供了一个新的教学模块开发的范式。原来的教学模块 就像静态调用的DLL,而现在我们希望这个教学模块能像插槽一样即插即用。
该怎么做?既然是即插即用,那么就得请出我们的动态调用DLL 方法,接下来我将给出我的框架设计。
框架设计?
框架设计分为教学模块设计和主框架接口设计,这两部分实际上都是对主框架的设计,不过涉及的内容不一样。
教学模块框架
教学模块框架的涉及我需要给出一张图来做表示:
这个部分看图吧,我懒得解释太多了,这个图我觉得写的相当清楚了。
流程如下:
1.通过读取配置文件确定有哪些模块是可以尝试去调用的
2.在本地文件夹中检索可以调用的模块是否存在
3.调用教学模块约定好的方法来确定当前模块是否可用。
4.读取本地锁控,确定指定模块是否有锁控权限。
注1:因为是动态加载的DLL,那么DLL就必须提供类C接口,也就是extern "c" __del什么的,我忘了,反正就这么回事,自己百度查一下吧。
主框架的接口设计:
如图所示,我们在Interface_Kernel中提供了整个主程序中挂载的所有功能模块的单例调用接口,并在Interface_Kernel的单例中进行管理,然后再通过单例的方式直接向功能模块申请功能。这样既避免了大量重复啰嗦的消息码发来发去,也可以减少很多重复开发的工作量。
这样操作,主框架就不需要提供一个单独的类来管理教学模块和与教学模块进行交互了,而是可以只需要关心教学模块的启动、关闭、显示、隐藏 即可,其他的功能都由Interface_kernel单独交互即可。
这里我写了一个完整的工程,但由于代码是公司的财产,在此我不能开源所有的代码,如果你是将来维护开发的人员,你应该可以根据这篇博客了解到为什么主框架代码中会有接口类还有一个Interface_Kernel,原因也很简单,因为每次外部绑定主程序的时候,都会实例化一个新的接口,需要一个核心来管理所有的接口类实例。
至于说教学模块DLL的管理,也是类似的,但是这里就不展开细聊了。
总结
COM组件为功能模块的集中管理提供了可能,同时也为教学模块的独立开发提供了可能。
整个新框架和旧框架的核心思想区别就是:就框架把所有的教学模块都当成了主程序的一部分。
而新的框架中主程序其实只是为所有的教学模块提供各种各样的服务,比如语音、视频等服务,教学模块只需要调用指定的COM接口就可以直接调到主程序中的工具,而不需要再进行模块间的交互。而教学模块本身也只需要提供开启、关闭、显示、隐藏、认证五个接口,不需要再像之前一样写一大坨东西管理教学模块了。
这样既为后续模块化开发提供了更多的便利,也让主程序更加简洁,减少了很多不必要的重复开发。
如果有什么讲的不够详细的地方欢迎站内私信,我会尽量解答。
【大型软件开发】浅谈大型Qt软件开发(二)面向未来开发——来自未来的技术:COM组件。我如何做到让我们的教学模块像插件一样即插即用,以及为什么这么做。的更多相关文章
- [IC]浅谈嵌入式MCU软件开发之中断优先级与中断嵌套
转自:https://mp.weixin.qq.com/s?__biz=MzI0MDk0ODcxMw==&mid=2247483680&idx=1&sn=c5fd069ab3f ...
- 浅谈大型web系统架构
动态应用,是相对于网站静态内容而言,是指以c/c++.php.Java.perl..net等服务器端语言开发的网络应用软件,比如论坛.网络相册.交友.BLOG等常见应用.动态应用系统通常与数据库系统. ...
- 转:浅谈大型web系统架构
浅谈大型web系统架构 动态应用,是相对于网站静态内容而言,是指以c/c++.php.Java.perl..net等服务器端语言开发的网络应用软件,比如论坛.网络相册.交友.BLOG等常见应用.动态应 ...
- 浅谈OA办公软件市场行情
3.原文:http://www.jiusi.net/detail/472__776__3999__1.html 关键词:oa系统,OA办公软件 浅谈OA办公软件市场行情 中国的OA办公软件市场历经20 ...
- 【ZZ】浅谈大型web系统架构 | 菜鸟教程
浅谈大型web系统架构 http://www.runoob.com/w3cnote/large-scale-web-system-architecture.html
- 浅谈关于QT中Webkit内核浏览器
关于QT中Webkit内核浏览器是本文要介绍的内容,主要是来学习QT中webkit中浏览器的使用.提起WebKit,大家自然而然地想到浏览器.作为浏览器内部的主要构件,WebKit的主要工作是渲染.给 ...
- springboot开发浅谈 2021/05/11
学习了这么久,本人希望有时间能分享一下,这才写下这篇浅谈,谈谈软件,散散心情. 这是本人的博客园账号,欢迎关注,一起学习. 一开始学习springboot,看了好多网站,搜了好多课程.零零落落学了一些 ...
- Android开发-浅谈架构(二)
写在前面的话 我记得有一期罗胖的<罗辑思维>中他提到 我们在这个碎片化 充满焦虑的时代该怎么学习--用30%的时间 了解70%该领域的知识然后迅速转移芳草鲜美的地方 像游牧民族那样.原话应 ...
- Python测试开发-浅谈如何自动化生成测试脚本
Python测试开发-浅谈如何自动化生成测试脚本 原创: fin 测试开发社区 前天 阅读文本大概需要 6.66 分钟. 一 .接口列表展示,并选择 在右边,点击选择要关联的接口,区分是否要登录, ...
- Android蓝牙开发浅谈(转)
http://www.eoeandroid.com/thread-18993-1-1.html 对于一般的软件开发人员来说,蓝牙是很少用到的,尤其是Android的蓝牙开发,国内的例子很少 A ...
随机推荐
- python同时识别多张人脸(运用face_recognition)
之前发的博客和网上流传的代码严格来说都只算得上是人脸检测,不能区别人脸,今天来说说真的人脸识别 篇幅所限,就举两张人脸的例子了,本程序需要安装face_recognition 下面是全部源代码: im ...
- Django开发汇总
基本配置 # 设置数据库为使用的mysql DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'libr ...
- Rust Aya 编写 eBPF 程序
本文地址:https://www.ebpf.top/post/ebpf_rust_aya 1. 前言 Linux 内核 6.1 版本中有一个非常引人注意的变化:引入了对 Rust 编程语言的支持.Ru ...
- perl哈希嵌套和引用的使用
数组,哈希嵌套 数组,哈希的引用 1.哈希的嵌套和引用 %hash = ( 'group1', {'fruit', 'banana', 'drink', 'orange juice', 'vegeta ...
- 2022ICPC区域赛参后感悟
第一次参加正式的大类赛事,在某种程度上挺激动的.我呢,可以说是刚步入竞赛一年,在此期间遇见了一些志同道合的朋友,最重要的是遇见了我的队友. 开始前,我幻想过我们小队可以超常发挥,拿取学校中第一个区域赛 ...
- HTTPS详解一
前言 作为一个有追求的程序员,了解行业发展趋势和扩充自己的计算机知识储备都是很有必要的,特别是一些计算机基础方面的内容,就比如本篇文章要讲的计算机网络方面的知识.本文将为大家详细梳理一下 HTTPS ...
- C++初阶(vector容器+模拟实现)
迭代器 四种迭代器 容器类名::iterator 迭代器名;//正向迭代器 容器类名::const_iterator 迭代器名;//常量正向迭代器,const修饰,只能用于读取容器内的元素,不能改变其 ...
- 关于Android12安装apk出现-108异常INSTALL_PARSE_FAILED_MANIFEST_MALFORMED的解决方法
原文地址:关于Android12安装apk出现-108异常INSTALL_PARSE_FAILED_MANIFEST_MALFORMED的解决方法 - Stars-One的杂货小窝 问题描述 用户的小 ...
- c++题目:数迷
c++题目:数迷 题目 [题目描述] 给出含有N×N个格子的正方形表格,要求每个格子都填上一个个位数(范围1-N),使得每行.每列以及同一斜线上的数字都不同.部分格子已经填好数字.求满足题意的方案数. ...
- oracle 内置函数(二)字符函数
主要函数: 大小写转换函数 获取子字符串函数(字符串截取) 获取字符串长度函数 字符串连接函数 去除子字符串函数 字符替换函数 字符串出现次数 字符串按照特定符号拆分多行 一.大小写转换 1.uppe ...