尽量不写一行if...elseif...写出高质量可持续迭代的项目代码

news2024/11/18 10:19:35

背景

无论是前端代码还是后端代码,都存在着定位困难,不好抽离,改造困难的问题,造成代码开发越来越慢,此外因为代码耦合较高,总是出现改了一处地方,然后影响其他地方,要么就是要修改一个逻辑,结果耗费了大量时间进行改造,代码写得耦合较高,造成这种情况的原因无非就是程序员本身没有管理者的思维,喜欢取巧,合并,凑数,偷懒造成的,说白了,想比做的少,更多的是先动手去干,而不是先想好过去/现在/未来三种情况再干,这样撸着撸着,就会将代码撸得让自己越来越反感,越枯燥!

新语法,高阶语法无心尝试,这些东西并非为了装逼用,大佬创造他们并设为标准,就是为了解决代码可能存在的问题。

问题一:顺向思维

需求交接后,并不对旧逻辑 + 新逻辑进行整合过滤,而忙于添加一个 if...elseif 就着手开发了,一个例子就是智能养号,拿到需求后,快速得出 3 个按钮的组合是 4 种可能,实际上整体思考后,会发现其中 团队开关开启和互养池开关开启 只走互养池逻辑,也即 3 个逻辑。

以下是伪代码,主要讲述主逻辑展示的必要性,子逻辑仍然要遵循一条线法继续拆分函数,直到最小颗粒度的函数体,才去实现,而函数体不应该超过 100 行,否则很有必要继续拆分

@router.post('/target-wid')
async def get_target_wid(
    user_id: int = Depends(get_user_id),
    company_id: int = Depends(get_company_id),
    item: TargetWhatsappIdGetParam = Body()
):
    '''
    第一层代码纯主逻辑 绝无细节 未来还可能有更多主逻辑
    而未来追加新逻辑链路只是再加一行代码而已
    第一层逻辑绝无 elsif 因为要一条线到底
    '''
    if huyang.switch:
        return huyang.match_numbers()
    if team_huyang.switch:
        return team_huyang.match_numbers()
    return selfyang.match_numbers()

问题二:不封装函数

无论是前端还是后端,现在都已经有了面向对象的概念,尤其是 ES6 的存在,相同逻辑的东西可以封装成函数,但是目前前端的代码封装密集度不够。仍然是面向过程的开发。

问题三:面向对象

python 本身已支持面向对象,而后端程序员都是科班出身,同时又都学过 java,但是代码写得不尽人意,仍然是赤裸裸地面向过程,更别提面向切面了,连个装饰器都没有尝试写过,真的不需要吗?还是懒得去总结代码,划分出来这些东西?

model 是什么?

model 是编程语言映射数据库字段的中转对象,将 mysql 二进制字符对应转化为编程语言的类型,每条记录对应一个 model

  1. model 是编程语言对象,是对象除了属性还是有行为,行为就是静态函数或者成员函数

    1. 静态函数往往处理本表的一些转换性操作,例如创建对象时的前置数据处理,保存对象前的前置处理,获取对象后的后置处理,都是静态成员函数的工作,不针对于某个对象,而是针对于所有对象的面向切面的操作

    2. 成员函数,往往是对于从数据库查询了特定记录,针对这一条记录进行数据的处理,处理完成后返回某值,或者入库

    3. 以上两个操作都是 model 的操作范畴

service 是什么?

service 是针对功能模块下的一堆逻辑的操作集合,它含有各种函数,又可以将各种函数进行组合再构成新函数,主要的目的就是将逻辑进行最大化的封装,不暴露细节,而细节都在私有函数里

举个例子我想下单,那么就有 OrderService,OrderService 对外提供一个 public 函数,createOrder(orderInfo, userId),那么 OrderService.createOrder(orderInfo, userId),创建完订单后还要干什么,那就是其他各种公共函数了,createOrder 函数里面例如提取可用优惠券,drawCanUseCoupons(userId),这个就是私有函数,提取后还得计算优惠券的匹配情况 getMatchCoupons(orderInfo, coupons)等等各类私有函数,这些私有函数在取消订单时也会用到,但是你单独使用 drawCanUseCoupons(userId),例如用户卡券包,这时你发现可以再抽出一个 UserService,将drawCanUseCoupons(userId)挪过去,因为这个跟订单信息无关,跟用户信息有关,这就是 Service

service 存在意义?

service 存在意义是将需求主逻辑变得特别简洁易懂,不暴露任何细节,如图:

这是一个巨复杂的创建订单的前置校验,如果我直接将 createOrder 暴露出来,这个代码得有 1000 行,但是为了要保持函数代码的体积,这里只将主逻辑呈现,细节继续细化

而 createOrder 主逻辑也仅仅 40 行代码

createOrder 主体逻辑也是由大量其他 model 和 service 逻辑函数组合而成

这样写的好处就是主逻辑结构一直很清晰,自己需要记忆的东西是分层的,每次进入一个函数,或者跳出一个函数,都不用带着巨大的上下文来思考,只需要集中在这个单元函数里,保证单元函数的正确性即可,整体逻辑组合在一起,是不可能出现大差错的。

问题三:重复函数的使用

程序员有个习惯,尤其是面向过程的习惯

看一个 python 代码,这里为了要承接上面代码最终结果的过滤,就用了大量的 if...else 以及嵌套的 if...else

如果改造完了之后,应该就是 3 个主逻辑函数,分别调用 NurtureService.xxx1/2/3 三种逻辑,每个函数都是 return,针对 filter,再各自调用 NurtureService.filter(numbers),如果 filter 里面还需要 if...else 判断,则再将 filter 拆分为 filter1/2/3,也即将逻辑改为一顺而下,而非底层汇编语言的来回 jump,每个 while 和每个 if 都是一次 jump,jump 计算机会中断,人脑也会中断,阅读识别都不方便

而函数对于计算机来说,用完即焚,会快速清理内存,而上面这种面向过程的代码,就很难做到清理内存,if 过程中产生的变量都会存在内存里,直到这个函数运行完毕。

代码重复一定要封装,函数重复没问题,函数名在底层就是 16 进制,而且并不是重复存储,所以大胆地将函数重复调用,将代码逻辑实现完美解耦。

下面就是一个好例子

问题四:善用文件夹

程序员养成了一个习惯,就是通过命名前缀来区分代码文件,加多了就造成命名冗长,同时单个文件夹下的代码文件巨多,看这里 OrderController,我都用一个命名,通过文件夹的方式进行区分,任何语言都有命名空间的概念,所以这样既能让代码命名简洁,不来回乱起,还能保持层次分明

问题五:控制反转和反射机制

我们的习惯是一个类的处理逻辑必须由自己实现,也即 order.createOrder,实际上我们可以将这种权力交出去,让其他对象来处理它,例如

OrderService.createOrder(order),如果前面的 OrderService 可以通过上面的那种命名空间的方式用反射机制,这种方式可以根据传入参数,这种方式可有效减少 if...else 的使用,但也造成了代码的不易读,最好用 Factory 工厂模式,通过传入参数,显式地调用具体的类,这样可读性就高了很多,代码可维护性也提高了很多,而且每个逻辑都是隔离的,改动起来不会对其他逻辑产生任何影响

class_name = "api.OrderService"
my_class = globals()[class_name]

# 创建对象实例
instance = my_class()

# 调用对象的方法
print(instance.createOrder(order))

问题六:很少对单函数进行异常预测和收集

如果上面 5 个问题都得到了很好的处理,那么剩下的就是异常的预测和收集,每个单元函数都会出现异常,go 语言就很好,返回值总是,result,err = xxxx(),其中 err 就是一个错误,错误产生后,可以通过人为判断是否向上抛出,或者自行消化,再或者 push 到一个错误收集器里

顶级函数外层都会进行错误捕获和处理,这里 PHP 做得比较粗糙了些

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1896793.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

文本超长省略的几种方式(vue)

第一种&#xff0c;纯css 在给容器设置宽度后&#xff0c;使用css来省略文本超长部分&#xff0c;但是这样就看不到全部的内容 <template><div class"content"><div class"text">{{ text }}</div></div> </template>&…

ubuntu 安装说明

最近准备学习Linux&#xff0c;所以下载了最新的ubuntu server版本24.04&#xff0c;将安装步骤记录下来供参考。 1.安装 挂载光驱和iso文件&#xff0c;启动虚拟机。启动后&#xff0c;你会看到 GRUB 菜单上有两个选项&#xff1a; Try or Install Ubuntu Server 和 Test mem…

防水M7/8“航空法兰插座端子

防水M7/8"航空法兰插座广泛应用于传感器与执行器、电机马达、包装与传送系统、户外LED模块、轨道交通、船舶雷达与导航&#xff0c;以及现场总线DeviceNet与NMEA 2000开放型网络系统等应用领域。M7/8"插座作为一种常见的电气连接器件&#xff0c;在传感器领域中扮演着…

快手矩阵系统源码:技术优势解析

在短视频和直播行业迅猛发展的今天&#xff0c;快手凭借其强大的矩阵系统源码&#xff0c;为用户提供了多端管理、多账号管理、素材管理、视频批量上传、AI视频制作和定时发布等一系列高效功能。本文将深入探讨快手矩阵系统源码的多项优势&#xff0c;以及这些功能如何助力内容…

如何改善提示词,让 GPT-4 更高效准确地把视频内容整体转换成文章?

&#xff08;注&#xff1a;本文为小报童精选文章。已订阅小报童或加入知识星球「玉树芝兰」用户请勿重复付费&#xff09; 让我们来讨论一下大语言模型应用中的一个重要原则 ——「欲速则不达」。 作为一个自认为懒惰的人&#xff0c;我一直有一个愿望&#xff1a;完成视频制作…

气象观测站:观测和记录各种气象要素

在广袤无垠的蓝天下&#xff0c;气象观测站如同一个个静默的守护者&#xff0c;默默记录着风云变幻&#xff0c;守护着大地的安宁。 一、气象观测站&#xff1a;守护天空的“千里眼” 气象观测站&#xff0c;顾名思义&#xff0c;就是专门用于观测和记录各种气象要素的站点。它…

UVa1265/LA4848 Tour Belt

UVa1265/LA4848 Tour Belt 题目链接题意分析AC 代码 题目链接 本题是2010年icpc亚洲区域赛大田赛区的F题 题意 给出一个有n个结点m条边的加权无向图G&#xff08;2≤n≤5000&#xff0c;1≤m≤n(n-1)/2&#xff09;&#xff0c;满足如下条件的结点集B&#xff08;2≤|B|≤n&am…

2025深圳国际消费电子展览会

2025深圳国际消费电子展览会 时间&#xff1a;2025年06月25-27日 地点&#xff1a;深圳国际会展中心(新馆) 详询主办方陆先生 I38&#xff08;前三位&#xff09; I82I&#xff08;中间四位&#xff09; 9I72&#xff08;后面四位&#xff09; 展会介绍&#xff1a; 20…

SAP-SD同一物料下单价格确不同

业务说明&#xff1a; 业务部门反馈&#xff0c;同一物料下销售订单时&#xff0c;价格确不同。 那么这个价格是怎么取到的呢&#xff1f; 逻辑说明&#xff1a; 1、首先查看销售订单 可以看到相同物料价格是不同的&#xff0c;条件类型都是ZPR5&#xff0c;但是客户是不同…

【新能源时代!看大模型(LLMs)如何助力汽车自动驾驶!】

文末有福利&#xff01; 引言 本文主要介绍大模型(LLMs)如何助力汽车自动驾驶&#xff0c;简单来说&#xff0c;作者首先带大家了解大模型的工作模式&#xff0c;然后介绍了自动驾驶大模型的3大应用场景&#xff0c;最后指出自动驾驶大模型将会是未来的发展趋势&#xff0c;只…

View->裁剪框View的绘制,手势处理

XML文件 <?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android…

CFS三层内网渗透——第二层内网打点并拿下第三层内网(三)

目录 八哥cms的后台历史漏洞 配置socks代理 ​以我的kali为例,手动添加 socks配置好了&#xff0c;直接sqlmap跑 ​登录进后台 蚁剑配置socks代理 ​ 测试连接 ​编辑 成功上线 上传正向后门 生成正向后门 上传后门 ​内网信息收集 ​进入目标二内网机器&#xf…

【linux进程】进程地址空间(什么是进程地址空间?为什么要有进程地址空间?)

目录 一、前言 二、 程序的地址空间是真实的 --- 物理空间吗&#xff1f; 三、进程地址空间 &#x1f525; 操作系统是如何建立起进程与物理内存之间的联系的呢&#xff1f; &#x1f525;什么是进程地址空间&#xff1f; &#x1f525;为什么不能直接去访问物理内存&a…

Protobuf(三):理论学习,简单总结

1. Protocol Buffers概述 Protocol Buffers&#xff08;简称protobuf&#xff09;&#xff0c;是谷歌用于序列化结构化数据的一种语言独立、平台独立且可扩展的机制&#xff0c;类似XML&#xff0c;但比XML更小、更快、更简单protobuf的工作流程如图所示 1.1 protobuf的优点…

Python酷库之旅-第三方库Pandas(003)

目录 一、用法精讲 4、pandas.read_csv函数 4-1、语法 4-2、参数 4-3、功能 4-4、返回值 4-5、说明 4-6、用法 4-6-1、创建csv文件 4-6-2、代码示例 4-6-3、结果输出 二、推荐阅读 1、Python筑基之旅 2、Python函数之旅 3、Python算法之旅 4、Python魔法之旅 …

工业废水中镍超标怎么办?含镍废水处理方法有哪些?

镍是一种存在于自然界中的过渡金属。镍在土壤和岩石中的存量丰富&#xff0c;大部分镍已被氧化&#xff0c;或与其他元素结合成化合物。   含镍废水主要来源于电镀、合金制造、金属表面处理、电子等行业。这些行业在生产过程中&#xff0c;通常会使用含有镍离子的化学试剂&a…

kali改回官方源后更新失败

官方源&#xff1a; deb http://http.kali.org/kali kali-rolling main non-free contrib deb-src http://http.kali.org/kali kali-rolling main non-free contrib在文件 /etc/cat/sources.list中将官方源修改为&#xff1a; deb http://http.kali.org/kali kali-rolling ma…

等保测评需要什么SSL证书

在进行信息安全等级保护&#xff08;简称“等保”&#xff09;测评时&#xff0c;选择合适的HTTPS证书对于确保网站的安全性和合规性至关重要。以下是在等保测评中选择HTTPS证书时应考虑的因素&#xff1a; 国产证书&#xff1a; 等保测评倾向于使用国产品牌的SSL证书&#x…

科普文:一文搞懂jvm实战(二)Cleaner回收jvm资源

概叙 在JDK9中新增了Cleaner类&#xff0c;该类的作用是用于替代finalize方法&#xff0c;更有效地释放资源并避免内存泄漏。 在JEP260提案中&#xff0c;封装了大部分Sun包内部的API之余&#xff0c;还引入了一些新的API&#xff0c;其中就包含着Cleaner这个工具类。Cleaner承…

JAVA程序打包时报错,但是运行时正常。

报错&#xff1a;Could not transfer artifact com.alibaba:fastjson:pom:1.2.83 from/to clojars... 背景&#xff1a;需要将fastjson从1.2.70升级到1.2.83&#xff1b;并且编译环境是局域网不可以连接互联网&#xff1b;每个项目组都是独立的私有仓库。 操作&#xff1a;在本…