尽量不写一行if...elseif...写出高质量可持续迭代的项目代码
背景
无论是前端代码还是后端代码,都存在着定位困难,不好抽离,改造困难的问题,造成代码开发越来越慢,此外因为代码耦合较高,总是出现改了一处地方,然后影响其他地方,要么就是要修改一个逻辑,结果耗费了大量时间进行改造,代码写得耦合较高,造成这种情况的原因无非就是程序员本身没有管理者的思维,喜欢取巧,合并,凑数,偷懒造成的,说白了,想比做的少,更多的是先动手去干,而不是先想好过去/现在/未来三种情况再干,这样撸着撸着,就会将代码撸得让自己越来越反感,越枯燥!
新语法,高阶语法无心尝试,这些东西并非为了装逼用,大佬创造他们并设为标准,就是为了解决代码可能存在的问题。
问题一:顺向思维
需求交接后,并不对旧逻辑 + 新逻辑进行整合过滤,而忙于添加一个 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
-
model 是编程语言对象,是对象除了属性还是有行为,行为就是静态函数或者成员函数
-
静态函数往往处理本表的一些转换性操作,例如创建对象时的前置数据处理,保存对象前的前置处理,获取对象后的后置处理,都是静态成员函数的工作,不针对于某个对象,而是针对于所有对象的面向切面的操作
-
成员函数,往往是对于从数据库查询了特定记录,针对这一条记录进行数据的处理,处理完成后返回某值,或者入库
-
以上两个操作都是 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 做得比较粗糙了些
相关文章:
尽量不写一行if...elseif...写出高质量可持续迭代的项目代码
背景 无论是前端代码还是后端代码,都存在着定位困难,不好抽离,改造困难的问题,造成代码开发越来越慢,此外因为代码耦合较高,总是出现改了一处地方,然后影响其他地方,要么就是要修改…...
xcrun: error: unable to find utility “simctl“, not a developer tool or in PATH
目录 前言 一、问题详情 二、解决方案 1.确认Xcode已安装 2.安装Xcode命令行工具 3.指定正确的开发者目录 4. 确认命令行工具路径 5. 更新PATH环境变量 前言 今天使用cocoapods更新私有库的时候,遇到了"xcrun: error: unable to find utility &…...
【linux高级IO(一)】理解五种IO模型
💓博主CSDN主页:杭电码农-NEO💓 ⏩专栏分类:Linux从入门到精通⏪ 🚚代码仓库:NEO的学习日记🚚 🌹关注我🫵带你学更多操作系统知识 🔝🔝 Linux高级IO 1. 前言2. 重谈对…...
前端引用vue/element/echarts资源等引用方法Blob下载HTML
前端引用下载vue/element/echarts资源等引用方法 功能需求 需求是在HTML页面中集成Vue.js、Element Plus(Element UI的Vue 3版本)、ECharts等前端资源,使用Blob下载HTML。 解决方案概述 直接访问线上CDN地址:简单直接,…...
昇思MindSpore学习笔记2-01 LLM原理和实践 --基于 MindSpore 实现 BERT 对话情绪识别
摘要: 通过识别BERT对话情绪状态的实例,展现在昇思MindSpore AI框架中大语言模型的原理和实际使用方法、步骤。 一、环境配置 %%capture captured_output # 实验环境已经预装了mindspore2.2.14,如需更换mindspore版本,可更改下…...
uniapp实现图片懒加载 封装组件
想要的效果就是窗口滑动到哪里,哪里的图片进行展示 主要原理使用IntersectionObserver <template><view><image error"HandlerError" :style"imgStyle" :src"imageSrc" :id"randomId" :mode"mode&quo…...
持续交付:自动化测试与发布流程的变革
目录 前言1. 持续交付的概念1.1 持续交付的定义1.2 持续交付的核心原则 2. 持续交付的优势2.1 提高交付速度2.2 提高软件质量2.3 降低发布风险2.4 提高团队协作 3. 实施持续交付的步骤3.1 构建自动化测试体系3.1.1 单元测试3.1.2 集成测试3.1.3 功能测试3.1.4 性能测试 3.2 构建…...
VBA常用的字符串内置函数
前言 在VBA程序中,常用的内置函数可以按照功能分为字符串函数、数字函数、转换函数等等,本节主要会介绍常用的字符串的内置函数,包括Len()、Left()、Mid()、Right()、Split()、String()、StrConV()等。 本节的练习数据表以下表为例ÿ…...
大数据面试题之Spark(7)
目录 Spark实现wordcount Spark Streaming怎么实现数据持久化保存? Spark SQL读取文件,内存不够使用,如何处理? Spark的lazy体现在哪里? Spark中的并行度等于什么 Spark运行时并行度的设署 Spark SQL的数据倾斜 Spark的exactly-once Spark的…...
AI绘画 Stable Diffusion图像的脸部细节控制——采样器全解析
大家好,我是画画的小强 我们在运用AI绘画 Stable Diffusion 这一功能强大的AI绘图工具时,我们往往会发现自己对提示词的使用还不够充分。在这种情形下,我们应当如何调整自己的策略,以便更加精确、全面地塑造出理想的人物形象呢&a…...
liunx离线安装Firefox
在Linux系统中离线安装Firefox浏览器,您需要先从Mozilla的官方网站下载Firefox的安装包,然后通过终端进行安装。以下是详细的步骤: 准备工作 下载Firefox安装包: 首先,在一台可以上网的电脑上访问Firefox官方下载页面…...
UNet进行病理图像分割
数据集链接:https://pan.baidu.com/s/1IBe_P0AyHgZC39NqzOxZhA?pwdnztc 提取码:nztc UNet模型 import torch import torch.nn as nnclass conv_block(nn.Module):def __init__(self, ch_in, ch_out):super(conv_block, self).__init__()self.conv nn…...
初二数学基础差从哪开始补?附深度解析!
有时候,当你推不开一扇门的时候,不要着急,试着反方向拉一下,或者横向拉一下。下面是小偏整理的初二数学基础差从哪开始补2021年,感谢您的每一次阅读。 初二数学基础差从哪开始补2021年 第一个问题是很多同学都…...
【C语言】return 关键字
在C语言中,return是一个关键字,用于从函数中返回值或者结束函数的执行。它是函数的重要组成部分,负责将函数的计算结果返回给调用者,并可以提前终止函数的执行。 主要用途和原理: 返回值给调用者: 当函数执…...
华为机试HJ13句子逆序
华为机试HJ13句子逆序 题目: 将一个英文语句以单词为单位逆序排放。例如“I am a boy”,逆序排放后为“boy a am I”所有单词之间用一个空格隔开,语句中除了英文字母外,不再包含其他字符 想法: 将输入的字符串通过…...
代码随想录day40 动态规划(5)
52. 携带研究材料(第七期模拟笔试) (kamacoder.com) 完全背包,可重复放入物品,需要用一维滚动数组从前往后遍历。 由于第0个物品和后面物品的转移方程没有区别,可以不额外初始化dp数组,直接用元素全0的d…...
FFmpeg 命令行 音视频格式转换
📚:FFmpeg 提供了丰富的命令行选项和功能,可以用来处理音视频文件、流媒体等,掌握命令行的使用,可以有效提高工作效率。 目录 一、视频转换和格式转换 🔵 将视频文件转换为另一种格式 🔵 指定…...
Jmeter使用JSON Extractor提取多个变量
1.当正则不好使时,用json extractor 2.提取多个值时,默认值必填,否则读不到变量...
c++ 设计模式 的课本范例(下)
(19) 桥接模式 Bridge,不是采用类继承,而是采用类组合,一个类的数据成员是类对象,来扩展类的功能。源码如下: class OS // 操作系统负责绘图 { public:virtual ~OS() {}virtual void draw(cha…...
结合数据索引结构看SQL的真实执行过程
引言 关于数据库设计与优化的前几篇文章中,我们提到了数据库设计优化应该遵守的指导原则、数据库底层的索引组织结构、数据库的核心功能组件以及SQL的解析、编译等。这些其实都是在为SQL的优化、执行的理解打基础。 今天这篇文章,我们以MySQL中InnoDB存…...
spark shuffle——shuffle管理
ShuffleManager shuffle系统的入口。ShuffleManager在driver和executor中的sparkEnv中创建。在driver中注册shuffle,在executor中读取和写入数据。 registerShuffle:注册shuffle,返回shuffleHandle unregisterShuffle:移除shuff…...
HTMLCSS(入门)
HTML <html> <head><title>第一个页面</title></head><body>键盘敲烂,工资过万</body> </html> <!DOCTYPE>文档类型声明,告诉浏览器使用哪种HTML版本显示网页 <!DOCTYPE html>当前页面采取…...
富格林:曝光可信策略制止亏损
富格林指出,相信大家都对黄金投资的价值空间有目共睹,现如今黄金市场波动频繁,因此不少投资者也开始加入该市场试图赢得额外的财富。但作为新手投资者贸贸然地进场操作,亏损的几率是很大的,因此要学会掌握正规平台曝光…...
Android --- Service
出自于此,写得很清楚。关于Android Service真正的完全详解,你需要知道的一切_android service-CSDN博客 出自【zejian的博客】 什么是Service? Service(服务)是一个一种可以在后台执行长时间运行操作而没有用户界面的应用组件。 服务可由其他应用组件…...
Vue3从入门到精通(三)
vue3插槽Slots 在 Vue3 中,插槽(Slots)的使用方式与 Vue2 中基本相同,但有一些细微的差异。以下是在 Vue3 中使用插槽的示例: // ChildComponent.vue <template><div><h2>Child Component</h2&…...
【FreeRTOS】同步与互斥通信-有缺陷的互斥案例
目录 同步与互斥通信同步与互斥的概念同步与互斥并不简单缺陷分析汇编指令优化过程 - 关闭中断时间轴分析 思考时刻 参考《FreeRTOS入门与工程实践(基于DshanMCU-103).pdf》 同步与互斥通信 同步与互斥的概念 一句话理解同步与互斥:我等你用完厕所,我再…...
Docker 安装 Python
Docker 安装 Python 在当今的软件开发领域,Docker 已成为一项关键技术,它允许开发人员将应用程序及其依赖环境打包到一个可移植的容器中。Python,作为一种广泛使用的高级编程语言,经常被部署在 Docker 容器中。本文将详细介绍如何在 Docker 中安装 Python,以及如何配置环…...
外泌体相关基因肝癌临床模型预测——2-3分纯生信文章复现——4.预后相关外泌体基因确定单因素cox回归(2)
内容如下: 1.外泌体和肝癌TCGA数据下载 2.数据格式整理 3.差异表达基因筛选 4.预后相关外泌体基因确定 5.拷贝数变异及突变图谱 6.外泌体基因功能注释 7.LASSO回归筛选外泌体预后模型 8.预后模型验证 9.预后模型鲁棒性分析 10.独立预后因素分析及与临床的…...
C++: Map数组的遍历
在C中,map是一个关联容器,它存储的元素是键值对(key-value pairs),其中每个键都是唯一的,并且自动根据键来排序。遍历map的方式有几种,但最常用的两种是使用迭代器(iterator…...
【Windows】Bootstrap Studio(网页设计)软件介绍及安装步骤
软件介绍 Bootstrap Studio 是一款专为前端开发者设计的强大工具,主要用于快速创建现代化的响应式网页和网站。以下是它的主要特点和功能: 直观的界面设计 Bootstrap Studio 提供了直观的用户界面,使用户能够轻松拖放元素来构建网页。界面…...
二维舵机颜色追踪,使用树莓派+opencv+usb摄像头+两个舵机实现颜色追踪,采用pid调控
效果演示 二维云台颜色追踪 使用树莓派opencvusb摄像头两个舵机实现颜色追踪,采用pid调控 import cv2 import time import numpy as np from threading import Thread from servo import Servo from pid import PID# 初始化伺服电机 pan Servo(pin19) tilt Serv…...
c进阶篇(四):内存函数
内存函数以字节为单位更改 1.memcpy memcpy 是 C/C 中的一个标准库函数,用于内存拷贝操作。它的原型通常定义在 <cstring> 头文件中,其作用是将一块内存中的数据复制到另一块内存中。 函数原型:void *memcpy(void *dest, const void…...
新手入门:无服务器函数和FaaS简介
无服务器(Serverless)架构的价值在于其成本效益、弹性和扩展性、简化的开发和部署流程、高可用性和可靠性以及使开发者能够专注于业务逻辑。通过自动化资源调配和按需计费,无服务器架构能够降低成本并适应流量变化,同时简化开发流…...
基于Transformer的端到端的目标检测 | 读论文
本文正在参加 人工智能创作者扶持计划 提及到计算机视觉的目标检测,我们一般会最先想到卷积神经网络(CNN),因为这算是目标检测领域的开山之作了,在很长的一段时间里人们都折服于卷积神经网络在图像处理领域的优势&…...
6.8应用进程跨网络通信
《计算机网络》第7版,谢希仁 理解socket通信...
redis布隆过滤器原理及应用场景
目录 原理 应用场景 优点 缺点 布隆过滤器(Bloom Filter)是一种空间效率很高的随机数据结构,它利用位数组和哈希函数来判断一个元素是否存在于集合中。 原理 数据结构: 位数组:一个由0和1组成的数组,初始…...
vue+openlayers之几何图形交互绘制基础与实践
文章目录 1.实现效果2.实现步骤3.示例页面代码3.基本几何图形绘制的关键代码 1.实现效果 绘制点、线、多边形、圆、正方形、长方形 2.实现步骤 引用openlayers开发库。加载天地图wmts瓦片地图。在页面上添加几何图形绘制的功能按钮,使用下拉列表(sel…...
「多模态大模型」解读 | 突破单一文本模态局限
编者按:理想状况下,世界上的万事万物都能以文字的形式呈现,如此一来,我们似乎仅凭大语言模型(LLMs)就能完成所有任务。然而,理想很丰满,现实很骨感——数据形态远不止文字一种&#…...
Redis深度解析:核心数据类型与键操作全攻略
文章目录 前言redis数据类型string1. 设置单个字符串数据2.设置多个字符串类型的数据3.字符串拼接值4.根据键获取字符串的值5.根据多个键获取多个值6.自增自减7.获取字符串的长度8.比特流操作key操作a.查找键b.设置键值的过期时间c.查看键的有效期d.设置key的有效期e.判断键是否…...
C语言 指针和数组——指针的算术运算
目录 指针的算术运算 指针加上一个整数 指针减去一个整数 指针相减 指针的关系比较运算 小结 指针的算术运算 指针加上一个整数 指针减去一个整数 指针相减 指针的关系比较运算 小结 指针变量 – 指针类型的变量,保存地址型数据 指针变量与其他类型…...
[C++][CMake][CMake基础]详细讲解
目录 1.CMake简介2.大小写?3.注释1.注释行2.注释块 4.日志 1.CMake简介 CMake是一个项目构建工具,并且是跨平台的 问题 – 解决 如果自己动手写Makefile,会发现,Makefile通常依赖于当前的编译平台,而且编写Makefile的…...
CCD技术指标
CCD尺寸,即摄象机靶面。原多为1/2英寸,现在1/3英寸的已普及化,1/4英寸和1/5英寸也已商品化。CCD像素,是决定了显示图像的清晰程度,。CCD是由面阵感光元素组成,每一个元素称为像素,像素越多&…...
SpringBoot系列——使用Spring Cache和Redis实现查询数据缓存
文章目录 1. 前言2. 缓存2.1 什么是缓存2.2 使用缓存的好处2.3 缓存的成本2.4 Spring Cache和Redis的优点 3. Spring Cache基础知识3.1 Spring Cache的核心概念3.2 Spring Cache的注解3.2.1 SpEL表达式3.2.2 Cacheable3.2.3 CachePut3.2.4 CacheEvict 4. 实现查询数据缓存4.1 准…...
【算法】(C语言):冒泡排序、选择排序、插入排序
冒泡排序 从第一个数据开始到第n-1个数据,依次和后面一个数据两两比较,数值小的在前。最终,最后一个数据(第n个数据)为最大值。从第一个数据开始到第n-2个数据,依次和后面一个数据两两比较,数值…...
iOS项目怎样进行二进制重排
什么是二进制重排 ? 在iOS项目中,二进制重排(Binary Reordering 或者 Binary Rearrangement)是一种优化技术,主要目的是通过重新组织应用程序的二进制文件中的代码和数据段,来提高应用程序的性能ÿ…...
CentOS中使用SSH远程登录
CentOS中使用SSH远程登录 准备工作SSH概述SSH服务的安装与启动建立SSH连接SSH配置文件修改SSH默认端口SSH文件传输 准备工作 两台安装CentOS系统的虚拟机 客户机(192.168.239.128) 服务器(192.168.239.129) SSH概述 Secure S…...
spring @Autowire注解作用
终于有人把Autowired注解讲清楚了,赞!!!_autowired-CSDN博客...
密码学原理精解【5】
这里写目录标题 移位密码概述代码 希尔密码( Z 256 Z_{256} Z256)待加密长度被3整除待加密长度不一定被3整除加解密文件 移位密码 概述 以 z 26 运算为例 , k 为密钥 加密: e k ( x ) ( x k ) m o d 26 解密: d k ( x ) ( x − k ) m o d 26 以z_{…...
Unity3D 资源管理YooAsset原理分析与详解
引言 Unity3D 是一款广泛应用于游戏开发、虚拟现实(VR)、增强现实(AR)等领域的强大游戏开发引擎。在开发过程中,资源管理是一项至关重要的任务,它直接影响到游戏的性能和用户体验。YooAsset 是一个基于 Un…...
npm install puppeteer 报错 npm ERR! PUPPETEER_DOWNLOAD_HOST is deprecated解决办法
npm install puppeteer 报错如下: npm ERR! PUPPETEER_DOWNLOAD_HOST is deprecated. Use PUPPETEER_DOWNLOAD_BASE_URL instead. npm ERR! Error: ERROR: Failed to set up Chrome v126.0.6478.126! Set "PUPPETEER_SKIP_DOWNLOAD" env variable to sk…...