我的第一个上位机软件「建议收藏」

我的第一个上位机软件「建议收藏」2019年即将过去,这一年最值得开心、高兴的事就是我参与研发的“全自动生化分析仪”终于上市了,并受到市场的欢迎;由于有非常给力的销售团队,机器的订单一直不断。当然机器研制成功是项目经理和团队的功劳,而我只是参与其中的一部分而已,但这对我而言有特殊的意义;因为这是我的第一个基于linux的商用上位机软件。虽然以前在windows平台折腾过java、C#、MFC的小上位机,但那些上位机无…

大家好,又见面了,我是你们的朋友全栈君。

       2019年即将过去,这一年最值得开心、高兴的事就是我参与研发的“全自动生化分析仪”终于上市了,并受到市场的欢迎;由于有非常给力的销售团队,机器的订单一直不断。当然机器研制成功是项目经理和团队的功劳,而我只是参与其中的一部分而已,但这对我而言有特殊的意义;因为这是我的第一个基于linux的商用上位机软件。虽然以前在windows平台折腾过java、C#、MFC的小上位机,但那些上位机无论从代码量和功能上都无法和这个商用上位机相提并论。当年在做毕业设计时,见识到了linux系统功能的强大,一直想从事linux系统的软件开发;但为了尽快找到工作,只能先找擅长的单片机和stm32的软件开发工作。然后利用业余时间再学习linux系统相关知识。由于缺乏正确的引导,学习linux系统的应用程序开发走了很多弯路;选择了一套课程,根据课程先学了linux的设备驱动开发,学习了linux的某个模块源代码;虽然这部分在后来的工作中也用到了一点点,但这毕竟和linux应用程序开发是两个方向的工作;到了2016年初才学会如何在linux上开发Qt应用程序;造化弄人,到了2016年底终于有机会让我开发基于linux的应用程序。

        由于加入项目组的时间比较晚,加上是第一次开发商用上位机,缺乏经验,没有针对需求做详细的软件架构设计,一上来就根据需求开始编码;这种方式开发一些学习软件没有问题,但是开发功能繁多的商用软件肯定不可取;就像垒一个鸡窝前期可以不用设计图纸,但是建一栋高楼大厦,如果前期没详细规划和设计图纸,那将会带来无尽的问题。前期没有详细得设计软件架构,就根据开发单片机软件的经验用C语言的思维去开发C++软件,在刚开始开发一些调试执行机构的软件时,还没察觉到有什么问题。随着不断的新增功能,代码量越来越大,特别是在处理测试数据时,这时就不断的暴露出一些致命的问题。导致项目经理在测试机器性能时,整个软件bug满天飞,黑屏不断。项目经理虽然一直在催进度,但并没给我很大的压力,而是一直相信我能改好。刚开始调试bug时手段比较单一,只是把程序的运行情况打印到控制台上,虽然这是很常用的调试手段,但局限性也很大;因为当机器在不同地方使用时就得在那的电脑安装串口调试助手才能知道机器运行情况,若是交到客户那使用呢?经过不断查询资料发现Qt提供了运行日志的功能,虽然之前有通信日志,但那远远不够;熟练掌握了Qt运行日志的功能后,就在软件加上这个功能;果然收到了很好的效果,不管机器在哪里运行,只要一出问题,就可以根据运行日志和通信日志很快定位到原因,而打印运行日志时就很考验经验了,打印多了影响软件性能,打印少了不利于定位原因。但在开发软件的阶段时要查看一些变量的值时,每次都得登录后台打开运行日志进行查看,显得很繁琐。根据开发单片机软件的经验,每次遇到bug都是仿真,因此就引进了GDB调试,由于所用开发环境版本比较低,无法使用一键远程调试,但是使用gdbserver的方式也可达到同样的目的;使用了GDB调试后可定位到软件运行的具体语句并查看变量的值;大大提高了开发效率。有次朋友问我当linux的应用程序崩溃时有没有获取Linux的core文件进行定位程序崩溃的原因;我直接回答:“没有!”;然后朋友就用鄙视的眼神看了我一眼,那种鄙视的眼神让我久久不能忘怀;没方法学艺不精,只能在鄙视中成长!然后查阅了大量资料并做了相关实验,了解linux的core文件是什么以及如何使用;原来linux的core文件就像飞机失事后的黑匣子;当linux的应用程序崩溃时导致黑屏,core文件会记录下应用程序最后运行的各种情况,然后再用GDB调试core文件即可定位到出问题的原因,甚至定位到具体哪一语句导致程序崩溃;有时根据core文件定位出问题的类型,然后根据运行日志再定位到具体原因;两种调试手段结合使用。在开发软件过程中总会遇到各种各样的bug,而丰富的调试手段将决定是否能很快定位原因并解决bug。从一开始遇到bug的慌张到最后的淡定;上述几种调试方法给了我很大的底气。

        虽然掌握了几种调试方法,可以比较快速定位bug原因;但保证不了整个工程的代码质量。由于前期缺乏整体软件架构设计,到了中后期,进入代码维护和新增需求时,修改代码时经常是“牵一发而动全身”,修复了一个bug往往会引进另一个bug;新增一个功能则是会牵动到其他的功能;整个软件工程就像一个豆腐渣工程。为了扭转这种颓势,买了很多书和在网上找各种相关的视频教程。经常有人问买那么多书看得完吗?当然是看不完,但一个本书只要帮助解决一个小问题就赚了;更何况有的书不但可以协助解决问题还可以带来有体系的知识点。找各种相关视频教程是为了看看其他大神写的代码,因为提高写代码的能力就是看大神写的优秀代码然后模仿;在以前购买的教程学习群里有人介绍了狄泰软件学院的课程,由于以前购买课程的阴影,刚开始我也犹豫了一段时间,后来遇到的问题实在太多,抱着试试的态度而且价格也不贵就买了一套Qt课程;看了课程后就有种“相见恨晚”的感觉。课程通过写几个小小项目来讲解知识点;看老师写小项目代码时经常感到醍醐灌顶,原来还可以这样写代码;其中项目界面的全用代码生成,为用代码生成界面提供了模板;还有把C/C++的各种基础知识巧妙灵活配合使用而不是简单的“if else”和“switch case”;例如把C/C++的“短路原则”、“条件表达式”和“逗号语句”的作用发挥得淋漓尽致使得代码简洁清晰;因之前看过整套C++视频,这些基础知识虽然都懂,之前却不知怎么样使用;这让我坚信了基础知识的重要,只有基础知识扎实才能写出有质量的代码和设计出工业水平的软件架构。看完了这些再对照自己写的代码,然后通过模仿课程的写法几乎重构了整个软件代码,也重新设计了整个软件的编码风格。

        虽然整个软件有了良好的编码风格,但却找不到解决界面与数据分离的方法;直到看了课程中讲解的自定义模型类,用分层思想实现了数据到视图的控制流程,每层用一个类表示,用自定义的模型类组合了标准模型类,灵活显示各种数据;定义数据源类操作底层数据文件,用于把数据对象转换成字符串写入数据文件,让上层代码只需操作数据对象即可,妥妥的面向对象编程;这样就使得程序结构层次分明,代码写起来简单明了便于维护。这套设计我只需做简单的修改,增加少量的代码,即可用于解决我的软件界面与数据分离的问题;这套设计还让我学会了如何面向对象编程,就是在解决问题时,先把问题抽象成类,然后再定义操作类解决问题后返回相应问题对象。这种思想在课程实现简易网络聊天软件时得到了进一步的体现。在解决网络通信的数据粘连时,定义了通信协议类,然后定义协议对象装配类用于把通信数据装配成协议对象并返回给上层代码处理;通过举一反三修改少量代码即可用于解决我软件的串口通信数据粘连的问题,相比于原来用C语言思维方式解决问题,代码显得有层次有模块,完全符合“强内聚弱耦合”的设计原则。

        有了灵活巧妙运用各种基础知识的模板,有了如何用代码生成界面的模板,有了界面和数据分离的模板,有了运用面向对象编程思维解决通信数据粘连的模板;接下来就是模仿这些模板写法,重构自己的软件代码;而整个工程代码将近十万行,几乎是全推倒式的重构;而现实情况不可能是接下来几个月不新增需求和修复bug;所以只能“乱中求治”,在新增功能和修复 bug时坚持“抠”一点时间或利用加班时间用于逐渐改善代码设计,逐渐使代码的质量越来越好。最终使整个工程代码层次分明,结构简洁清晰,模块化,为后期维护打坚实基础。

        在完成整个软件的功能中另一个困难就是各种非线性曲线的拟合,刚开始面对这种只有在研究生课程才会学到的数值分析束手无策;后来由于时间关系,这部分就交给另一个同事,他用开源库搞定了。但由于对其中各种拟合曲线的兴趣,我开始翻阅各种资料,慢慢发现可以看懂简易的样条曲线拟合推导过程;这更激起了我的兴趣,更加认真学样条曲线拟合推导的全部过程,学习的过程就像柯南破案一样,一点一点的接近真相,每次有进步一点都能让我兴奋不已;先是在马东升和董宁编写的《数值计算方法》学了样条曲线拟合的推导理论知识,并看懂其中的几道例题;然后在王晓华编写的《算法的乐趣》学会了把方程组变化成矩阵,通过克洛脱法分解成两个三角矩阵,再用追赶法求得方程组的解。最后在John H.Mathews和Kurtis D.Fink著的《Numberical Methodes Using MATLAB》了解了样条曲线端点约束的几种情况,对样条曲线有了全面的认识;同时也知道机器中样本曲线拟合适那种端点约束。结合几本书学到的知识点,最后编写成了代码,并且计算结果和用开源库拟合的曲线参数是一样的,这让我成就感爆棚。拟合曲线完成后,在计算测试结果时,则是让我学会了用牛顿迭代法求解一元三次方程;还有如何快速判断抛物线在一个区间内的单调性,妥妥复习了一下高中数学。

        从写下第一行代码到软件跟随机器上市,这个过程遇到过千千万万的问题,而每一个诡异的bug和问题背后都隐藏着一个低级错误,每当解决一个诡异的bug都能带来一点点成就感和一点点进步;这也是我从毕业后这几年来,一直坚持学习linux应用开发的原因,虽然这几年让我失去其他的很多东西,思想也有过波动,最后庆幸坚持了下来,终于有一款基于linux的商用上位机,也算是随了几年前的心愿。

                                                                                                                                                                               2019年12月31号

我的第一个上位机软件「建议收藏」

 

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/138253.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 示波器表笔旁边的夹子是什么_示波器的基础操作,初学者必看教程「建议收藏」

    示波器表笔旁边的夹子是什么_示波器的基础操作,初学者必看教程「建议收藏」正确接地在设置测量或处理电路时,正确地接地是一个重要步骤。示波器正确接地可以防止用户受到电击,用户正确接地可以防止电路受到损坏。示波器接地意味着把示波器连接到电器中性的参考点上,如接地。把示波器三头电源线查到连接接地装置的插座上,实现示波器接地。示波器接地对人身安全是必需的。如果高压接触没有接地的示波器机箱,不管是机箱的哪个部分,包括视乎已经绝缘的旋钮,都会发送电击。而在示波器正确接地时,电流会通…

    2022年8月31日
    5
  • 系统可靠性计算「建议收藏」

    系统可靠性计算「建议收藏」系统可靠性计算是软考考试的一个重点,近些年几乎每次考试都会考到,但这个知识点的难度不高,了解基本的运算公式,即可轻松应对。可靠性计算主要涉及三种系统,即串联系统、并联系统和冗余系统,其中串联系统和并联系统的可靠性计算都非常简单,只要了解其概念,公式很容易记住。冗余系统要复杂一些。在实际的考试当中,考得最多的就是串并混合系统的可靠性计算。所以要求我们对串联系统与并联系统的特点有基本的了解,对其计算…

    2022年7月26日
    8
  • 小红书用户画像分析_抖音用户画像分析及活跃时间点「建议收藏」

    小红书用户画像分析_抖音用户画像分析及活跃时间点「建议收藏」今天小编来和大家分享一下,抖音用户画像的分析和抖音用户的活跃时间点,1、重点的画像,是抖音受众人群高低线及分布率。2、查询数据的技巧,如果是产品的话参考到阿里指数上查看,如果查行业的话,可以在百度上查看行业报告。在看数据的时候,要清楚你要从数据中得到什么,给我们启发是什么?做抖音要了解抖音上都有哪些人群,找准相对应的人群才能达成转化。3、抖音视频的活跃大约时间上午高峰是12:00晚上…

    2022年6月11日
    211
  • 抖音数据统计_抖音直播带货数据分析(最新教程)

    抖音数据统计_抖音直播带货数据分析(最新教程)现在直播带货是一个热门趋势,它可以突破抖音挂购物车数量的限制,已经有不少商家通过直播带货实现流量变现了。那么,如何做好抖音直播就成了抖音电商玩家最大的需求。为此,飞瓜数据总结了几个抖音直播电商数据分析的维度和需要关注的关键指标:一.抖音直播电商数据分析的维度抖音直播电商数据分析需要围绕“带货”这个核心目标展开,这其中就涉及到“人、货、场”这三个概念,也就是抖音直播的流量、商品和直播间。这三个概念组…

    2022年5月18日
    96
  • c# listView1写入第一行第一列

    c# listView1写入第一行第一列listview的用法:1:首先申明一个行对象ListViewItemlist=newListViewItem(“a”);2:为行对象添加子项list.subitems.add(“b”);list.subitems.add(“c”);3:把行对象加到ListView中去,listview1.items.add(list);综上所述就在listview中添加了一行,如果你想添加多行,可

    2022年7月12日
    38
  • JAVA多线程面试题_java多线程的实现方式

    JAVA多线程面试题_java多线程的实现方式前言在看完《Java多线程编程核心技术》与《Java并发编程的艺术》之后,对于多线程的理解到了新的境界.先拿如下的题目试试手把.投行面试Q1:现在有线程T1、T2和T3。你如何确保T2线程在T1之后执行,并且T3线程在T2之后执行?答案:使用Thread.join()方法即可.当然JUC包内提供了CountDownLatch与CyclicBarrier工具…

    2022年8月29日
    4

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号