百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术文章 > 正文

纯干货:客户端代码框架设计(客户端开发框架)

ccwgpt 2024-10-19 03:11 28 浏览 0 评论

今天小豆君以第一人称视角,讲讲我做客户端开发的重构历程,并且在文中最后给大家指出我目前认为比较好的一个代码框架。


我把我的经历分为以下6个阶段:

阶段1:界面与业务代码混合

还记得刚毕业时,自己在学校也没怎么学习,代码基础可以说是一片空白,只知道一些基本的语法,凭着面试前死记硬背,勉强算是进入了一家公司,薪资呢也算是刚够吃饱饭的。

此时,我开发的是军工行业的一款桌面应用程序。我的代码都是在单个进程中开发的,而且业务逻辑也混合在界面类中,当另一个界面类想要获取到某个业务数据时,必须将另一个窗口类暴露出来。

随着代码量的增加,我的界面类越来越多,业务数据也越来越多。这就导致所有的业务和界面代码全部混合在一起,它们就像网一样,当需求关联到这些业务数据时,我很难从代码里面把它们清晰的拉出来。一旦发生错误,就像多米诺骨牌一样串联着很多个错误。

这使得我很难定位到真正的问题所在,按住葫芦起了瓢,刚刚修复了一个错误,谁想过一会儿测试又发现了新的问题。这让我痛苦不堪,看着其他人下班都早早回家,我却还在苦苦改bug,真是羡慕啊。

记得当时领导跟我讲得最多的是,小伙子的态度非常好,但技术能力就很一般了,还需要我多加把劲儿。为此,我暗下决心,对代码进行重构。


阶段2:界面与业务代码分离

为解决业务代码和界面相互嵌套造成的逻辑混乱,为此,我将业务代码和界面代码进行分离,就是我们平常说的前后端分离

核心点:

  1. 前端只处理布局、控件、样式、简单计算
  2. 后端只处理前端请求,为其提供业务数据

我用一个图大概表示如下

编辑切换为居中

界面与业务分离

结合上图

针对阶段1,有以下重要改动

1)前后端彻底分离

前端只负责:数据展示,界面操作,控件布局以及简单计算;

后端只负责:和数据库交互,和窗口类发送来的请求信息交互,返回前端所需数据

2)新增一张全局信号表,当然也可以将该信号表进行详细分类,分别放在不同的文件中

该表主要定义界面与业务的信号

信号和槽的命名方法:

  • req(request的前三个字母)开头的为请求信号,以on开头的为对应槽;
  • res(response的前三个字母)开头的为响应信号,以on开头的为对应槽。

上图中我为了获取用户信息,在信号表中将get_user分为两个信号req_get_user和res_get_user,业务代码使用槽on_req_get_user来处理请求,子界面A使用槽on_res_get_user来处理响应。

有些同学可能会觉得这是多此一举,在该窗口类A中定义一个获取用户信息的函数,当点击按钮时直接调用该函数岂不方便很多。然而这种做法是错误的,这又回到了我讲的阶段1中,业务代码和界面没有分开。

例如,此时又有一个子窗口B也需要获取用户信息,这时你有两种选择,一是把子窗口A中的代码复制过来再重新实现一遍,显然代码重复不可取;方法二是直接在A中把该函数设为公有,在B中引用A的方法。如果你使用方法二,当时觉得开发很快,但随着需求的不断变化,你会发现代码会越来越难维护,所有的东西都混在一起,你只能不断的往代码中贴补丁,最终整个框架爆掉。

那么,我们如果采用前后端分离的方式,针对以上界面类B想要获取用户信息,只需要在给类中也定义一个同名槽函数on_res_get_user绑定响应信号res_get_user即可获得用户信息。这代码看起来就舒服多了。


但是当我正在为自己的重构而沾沾自喜时,新的问题又出现了,由于客户量的增加,与之对应的数据也在不断攀升,由于我的代码查询大量数据占用了过多时间,从而出现界面出现卡死的情况,为此我又开始思考代码重构。


阶段3:使用多线程

解决界面卡死的一个比较好的办法是使用多线程,多线程大家都清楚,我就不过多解释了。

为此,我继续重构代码

?

编辑切换为居中

增加线程管理器处理前端请求

在线程管理器类中,新增线程池,每次接收到前端请求任务时,从线程池中取出线程执行任务。

这样,客户就不会因为复杂的sql查询而在界面前苦苦等待了。


阶段4:业务代码进行分层处理

在实现了多线程的处理方式后,我并没有高兴得太久,产品的需求更加变态,虽然前端部分的代码已经分离出来,但业务部分仍是一团糟,这又迫使我不得不再次进行重构,本次主要是对业务代码进行重构。

我的思路是参考java中的分层模型,但java里面分层比较复杂,客户端没必要做的那么做,为此我将其进行了简化。

  1. 预处理层:类似于网关,主要处理路由转发、请求过滤、请求埋点、业务监控等;
  2. 服务层(Service):主要处理具体业务请求;
  3. 管理层(Manager):通用业务处理层,主要封装第三方功能接口;对Service层通用能力的下沉,如缓存方案、中间件通用处理;与DAO层交互,对多个DAO的组合复用;
  4. 数据访问层(Dao):与数据库进行交互,并返回数据模型类对象。

?

编辑切换为居中

业务分层


阶段5:双进程or多进程

通过以上代码重构,我渐渐取得了领导的信任,我开始担任起技术组长的职务。随着团队成员的增多,每个人的技术水平参差不齐。C++这门语言只要有个指针引用错误,就会导致整个程序崩溃,有些客户需要保存的数据也会因此而丢失。用户体验实在是太差了,长此以往,我们的客户流失率也必然会升高。为此,我不得不对代码再一次重构。

因为之前一直使用的是单进程,所以为了不让程序彻底死掉,针对我们的业务需求,我采用了双进程模式。前端一个进程,后端一个进程。当然,开发者也可以选择多进程模式,例如谷歌浏览器,一个界面就是一个进程。即使崩溃也只影响到当前界面而已。具体的方案要根据实际业务需求来制定。

由于前面我已经做了前后端分离,本次重构很顺利地完成了。想想还是很happy的。


阶段6:加入自动化测试

尽管使用了多进程,但并没有真正意义上解决客户问题,产品质量仍然是问题。我们追求的是尽可能少地出现bug更低的缺陷率,我一定要加强测试,此时自动化测试进入了我的视线。

一般的测试方法,就是在界面上根据功能不停地点击,进行人工测试。当我们再次更新程序时,测试人员必须再次进行重复测试,回归测试等,耗时耗力。

下图是一个比较传统的测试分层:

?

编辑切换为居中

测试分层

测试分层的金字塔模型

  1. UiTest(塔顶):界面测试,一般测试主要集中在这一层,以人工点击方式为主。这一侧距离用户最近,距离代码最远,这就导致一旦发生错误,我们需要跟踪的链路非常长,定位问题相对比较困难,有时还很难复现问题。但由于其离客户最近,也最能体现完整的业务逻辑。
  2. UnitTest(塔底):单元测试,这一层相当于白盒测试了,主要以开发为主,自己编写测试用例脚本,对每一个函数进行测试。这一侧距离用户最远,代码最近,所以一旦发生错误,我们能够很容易定位到。如果我们能把这一层做好,客户端代码的稳健性就有了非常大的保证了。但是它需要消耗大量的时间和精力,且随着代码的变更,测试用例也必须实时更新。一般公司都不太具备这样的条件。
  3. ServiceTest(塔中):服务接口测试,这一层相对其它两层,不会像界面那样多变,也不会像单元测试那样需要巨量的测试用例。接口相对稳定,只要我能保证有足够的测试用例在,就基本能够保证我软件的稳定性。所以我选择在这一层做自动化测试,有了足够的用例后,不管是后面业务变更或是代码重构,我都有非常大的信心去实现,因为自动化测试是我质量的保证。


好了,以上基本就是我的客户端代码的框架设计之路。

欢迎关注:

微信公众号:小豆君编程分享

头条号:小豆君编程分享

相关推荐

一个基于.Net Core遵循Clean Architecture原则开源架构

今天给大家推荐一个遵循CleanArchitecture原则开源架构。项目简介这是基于Asp.netCore6开发的,遵循CleanArchitecture原则,可以高效、快速地构建基于Ra...

AI写代码翻车无数次,我发现只要提前做好这3步,bug立减80%

写十万行全是bug之后终于找到方法了开发"提示词管理助手"新版本那会儿,我差点被bug整崩溃。刚开始两周,全靠AI改代码架构,结果十万行程序漏洞百出。本来以为AI说没问题就稳了,结果...

OneCode低代码平台的事件驱动设计:架构解析与实践

引言:低代码平台的事件驱动范式在现代软件开发中,事件驱动架构(EDA)已成为构建灵活、松耦合系统的核心范式。OneCode低代码平台通过创新性的注解驱动设计,将事件驱动理念深度融入平台架构,实现了业务...

国内大厂AI插件评测:根据UI图生成Vue前端代码

在IDEA中安装大厂的AI插件,打开ruoyi增强项目:yudao-ui-admin-vue31.CodeBuddy插件登录腾讯的CodeBuddy后,大模型选择deepseek-v3,输入提示语:...

AI+低代码技术揭秘(二):核心架构

本文档介绍了为VTJ低代码平台提供支持的基本架构组件,包括Engine编排层、Provider服务系统、数据模型和代码生成管道。有关UI组件库和widget系统的信息,请参阅UI...

GitDiagram用AI把代码库变成可视化架构图

这是一个名为gitdiagram的开源工具,可将GitHub仓库实时转换为交互式架构图,帮助开发者快速理解代码结构。核心功能一键可视化:替换GitHubURL中的"hub...

30天自制操作系统:第六天:代码架构整理与中断处理

1.拆开bootpack.c文件。根据设计模式将对应的功能封装成独立的文件。2.初始化pic:pic(可编程中断控制器):在设计上,cpu单独只能处理一个中断。而pic是将8个中断信号集合成一个中断...

AI写代码越帮越忙?2025年研究揭露惊人真相

近年来,AI工具如雨后春笋般涌现,许多人开始幻想程序员的未来就是“对着AI说几句话”,就能轻松写出完美的代码。然而,2025年的一项最新研究却颠覆了这一期待,揭示了一个令人意外的结果。研究邀请了16位...

一键理解开源项目:两个自动生成GitHub代码架构图与说明书工具

一、GitDiagram可以一键生成github代码仓库的架构图如果想要可视化github开源项目:https://github.com/luler/reflex_ai_fast,也可以直接把域名替换...

5分钟掌握 c# 网络通讯架构及代码示例

以下是C#网络通讯架构的核心要点及代码示例,按协议类型分类整理:一、TCP协议(可靠连接)1.同步通信//服务器端usingSystem.Net.Sockets;usingTcpListene...

从复杂到优雅:用建造者和责任链重塑代码架构

引用设计模式是软件开发中的重要工具,它为解决常见问题提供了标准化的解决方案,提高了代码的可维护性和可扩展性,提升了开发效率,促进了团队协作,提高了软件质量,并帮助开发者更好地适应需求变化。通过学习和应...

低代码开发当道,我还需要学习LangChain这些框架吗?| IT杂谈

专注LLM深度应用,关注我不迷路前两天有位兄弟问了个问题:当然我很能理解这位朋友的担忧:期望效率最大化,时间用在刀刃上,“不要重新发明轮子”嘛。铺天盖地的AI信息轰炸与概念炒作,很容易让人浮躁与迷茫。...

框架设计并不是简单粗暴地写代码,而是要先弄清逻辑

3.框架设计3.框架设计本节我们要开发一个UI框架,底层以白鹭引擎为例。框架设计的第一步并不是直接撸代码,而是先想清楚设计思想,抽象。一个一个的UI窗口是独立的吗?不是的,...

大佬用 Avalonia 框架开发的 C# 代码 IDE

AvalonStudioAvalonStudio是一个开源的跨平台的开发编辑器(IDE),AvalonStudio的目标是成为一个功能齐全,并且可以让开发者快速使用的IDE,提高开发的生产力。A...

轻量级框架Lagent 仅需20行代码即可构建自己的智能代理

站长之家(ChinaZ.com)8月30日消息:Lagent是一个专注于基于LLM模型的代理开发的轻量级框架。它的设计旨在简化和提高这种模型下代理的开发效率。LLM模型是一种强大的工具,可以...

取消回复欢迎 发表评论: