重构改善既有代码的设计-学习(三):重新组织数据
1、拆分变量(Split Variable)
有些变量用于保存一段冗长代码的运算结果,以便稍后使用。这种变量应该只被赋值一次。
如果它们被赋值超过一次,就意味它们在函数中承担了一个以上的责任。如果变量承担多个责任,它就应该被替换(分解)为多个变量,每个变量只承担一个责任。同一个变量承担两件不同的事情,会令代码阅读者糊涂。
有两种情况除外:
- 循环变量(loop variable)会随循环的每次运行而改变(例如for(let i=0; i<10; i++)语句中的
i) - 结果收集变量(collecting variable)负责将“通过整个函数的运算”而构成的某个值收集起来。
2、字段改名(Rename Field)
将字段改为易于理解的名字,不要出现类似 int a等。
3、以查询取代派生变量(Replace Derived Variable with Query)
可变数据是软件中最大的错误源头之一。对数据的修改常常导致代码的各个部分以丑陋的形式互相耦合:在一处修改数据,却在另一处造成难以发现的破坏。很多时候,完全去掉可变数据并不现实,但我还是强烈建议:尽量把可变数据的作用域限制在最小范围。
例如:
get discountedTotal() {return this._discountedTotal;}
set discount(aNumber) {const old = this._discount;this._discount = aNumber;this._discountedTotal += old - aNumber;
}
改为:
get discountedTotal() {return this._baseTotal - this._discount;}
set discount(aNumber) {this._discount = aNumber;}
4、将引用对象改为值对象(Change Reference to Value)
在把一个对象(或数据结构)嵌入另一个对象时,位于内部的这个对象可以被视为引用对象,也可以被视为值对象。两者最明显的差异在于如何更新内部对象的属性:如果将内部对象视为引用对象,在更新其属性时,我会保留原对象不动,更新内部对象的属性;如果将其视为值对象,我就会替换整个内部对象,新换上的对象会有我想要的属性值。
如果把一个字段视为值对象,我可以把内部对象的类也变成值对象[mf-vo]。值对象通常更容易理解,主要因为它们是不可变的。一般说来,不可变的数据结构处理起来更容易。我可以放心地把不可变的数据值传给程序的其他部分,而不必担心对象中包装的数据被偷偷修改。我可以在程序各处复制值对象,而不必操心维护内存链接。值对象在分布式系统和并发系统中尤为有用。
何时不应该使用本重构手法?如果我想在几个对象之间共享一个对象,以便几个对象都能看见对共享对象的修改,那么这个共享的对象就应该是引用。这便是5中的情况了。
4的例子:
class Product {applyDiscount(arg) {this._price.amount -= arg;}
}
改为:
class Product {applyDiscount(arg) {this._price = new Money(this._price.amount - arg, this._price.currency);}
}
5、将值对象改为引用对象(Change Value to Reference)
一个数据结构中可能包含多个记录,而这些记录都关联到同一个逻辑数据结构。例如,我可能会读取一系列订单数据,其中有多条订单属于同一个顾客。遇到这样的共享关系时,既可以把顾客信息作为值对象来看待,也可以将其视为引用对象。如果将其视为值对象,那么每份订单数据中都会复制顾客的数据;而如果将其视为引用对象,对于一个顾客,就只有一份数据结构,会有多个订单与之关联。
如果顾客数据永远不修改,那么两种处理方式都合理。把同一份数据复制多次可能会造成一点困扰,但这种情况也很常见,不会造成太大问题。过多的数据复制有可能会造成内存占用的问题,但就跟所有性能问题一样,这种情况并不常见。
如果共享的数据需要更新,将其复制多份的做法就会遇到巨大的困难。此时我必须找到所有的副本,更新所有对象。只要漏掉一个副本没有更新,就会遭遇麻烦的数据不一致。这种情况下,可以考虑将多份数据副本变成单一的引用,这样对顾客数据的修改就会立即反映在该顾客的所有订单中。
相关文章:

重构改善既有代码的设计-学习(三):重新组织数据
1、拆分变量(Split Variable) 有些变量用于保存一段冗长代码的运算结果,以便稍后使用。这种变量应该只被赋值一次。 如果它们被赋值超过一次,就意味它们在函数中承担了一个以上的责任。如果变量承担多个责任,它就应该被…...
群狼调研(长沙品牌忠诚度测试)|广告效果测评方法
广告效果测评方法可以根据具体的目标和需求而有所差异,以下是一些常见的广告效果测评方法: 1.品牌调研和调查:通过定量或定性的调研和调查方法,评估广告对品牌认知、品牌形象和品牌偏好的影响,包括品牌知名度、品牌关联…...

Gradle学习笔记:Gradle的使用方法
文章目录 1.初始化项目2.构建脚本语言选择3.项目命名4.项目构建过程 1.初始化项目 创建一个test空文件夹,在该文件夹下打开终端,并执行命令:gradle init. 会有一个选项让你选择项目的类型。下面是每个选项的含义和用途: basic&am…...

少儿编程 2023年12月电子学会图形化编程等级考试Scratch二级真题解析(选择题)
2023年12月scratch编程等级考试二级真题 选择题(共25题,每题2分,共50分) 1、在制作推箱子游戏时,地图是用数字形式储存在电脑里的,下图是一个推箱子地图,地图表示如下:第一行( 111111)第二行( 132231) 第三行( 126621) 第四行( ) 第五行( 152321) 第六行( 111111 ) 根…...

基于Java+SpringMvc+vue+element实现上海汽车博物馆平台
基于JavaSpringMvcvueelement实现上海汽车博物馆平台 🍅 作者主页 央顺技术团队 🍅 欢迎点赞 👍 收藏 ⭐留言 📝 🍅 文末获取源码联系方式 📝 🍅 查看下方微信号获取联系方式 承接各种定制系统 …...

Sybase PowerDesigner15安装配置
1,软件介绍 Power Designer 是Sybase公司的CASE工具集,使用它可以方便地对管理信息系统进行分析设计,他几乎包括了数据库模型设计的全过程。利用Power Designer可以制作数据流程图、概念数据模型、物理数据模型,还可以为数据仓…...

基于物联网设计的水稻田智能灌溉系统(STM32+华为云IOT)
一、项目介绍 随着科技的不断发展和人们生活水平的提高,农业生产也逐渐向智能化、高效化的方向发展。水稻作为我国主要的粮食作物之一,其生长过程中的灌溉管理尤为重要。传统的灌溉方式往往依赖于人工观察和控制,不仅效率低下,而…...

【数据结构】数据结构初识
前言: 数据结构是计算存储,组织数据的方式。数据结构是指相互间存在一种或多种特定关系的数据元素的集合。通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。数据结构往往同高效的检索算法和索引技术有关。 Data Structure Vi…...
java多线程测试websocket demo(使用文件流)
这个demo主要是利用Java多线程来测试WebSocket通信。首先,创建一个WebSocket服务器和客户端,然后使用多线程来模拟多个客户端同时连接服务器进行通信。通过多线程测试,可以验证WebSocket通信的并发性能和稳定性。同时,可以通过多线…...

Tosei 自助网络店铺管理系统network_test.php_RCE漏洞复现
简介 Tosei 自助洗衣机是日本一家公司的产品,在 network_test.php 文件存在命令执行 漏洞复现 FOFA语法: body="tosei_login_check.php" 主要是日本 访问界面如下所示: 验证POC: /cgi-bin/network_test.php 拼接访问url: https://ip:port/cgi-bin/network_tes…...
uni-app 国际化
vue i18n v9的迁移后的$t()无法获取数组、对象 http://t.csdnimg.cn/WkCHy api:vue i18n [intlify] Not found ‘language’ key in ‘zh-Hans’ locale messages. [intlify] Fall back to translate ‘language’ key with ‘zh’ locale. [intlify] Not found ‘languag…...

git:git reset 和 git revert
在使用 git 进行项目开发的过程中,有时会出现错误提交的情况,这时就需要能够撤销错误的提交,将代码恢复到提交之前的样子。根据不同情况,可以使用 git reset 或 git revert 命令。 一. git reset git reset 的原理是修改 HEAD 的…...
LeetCode:670. 最大交换(Java 贪心)
目录 670. 最大交换 题目描述: 实现代码与解析; 贪心 原理思路: 670. 最大交换 题目描述: 给定一个非负整数,你至多可以交换一次数字中的任意两位。返回你能得到的最大值。 示例 1 : 输入: 2736 输出: 7236 解释…...

【STM32】STM32学习笔记-Unix时间戳(41)
00. 目录 文章目录 00. 目录01. Unix时间戳02. UTC/GMT03. 时间戳转换04. C 标准库 <time.h>05. 时间相关函数示例5.1 time函数5.2 gmtime函数5.3 localtime函数5.4 mktime函数5.5 ctime函数5.6 asctime函数5.7 strftime函数 06. 预留07. 附录 01. Unix时间戳 •Unix 时…...

2016年认证杯SPSSPRO杯数学建模B题(第一阶段)低分辨率下看世界全过程文档及程序
2016年认证杯SPSSPRO杯数学建模 B题 低分辨率下看世界 原题再现: 数码摄像技术被广泛使用于多种场合中。有时由于客观条件的限制,拍摄设备只能在较低的分辨率下成像。为简单起见,我们只考虑单色成像。假设成像的分辨率为 32 64,…...

16、Kafka ------ SpringBoot 整合 Kafka (配置 Kafka 属性 及对应的 属性处理类 解析)
目录 配置 Kafka 及对应的 属性处理类配置KafkaKafka配置属性的约定代码演示生产者相关的配置消费者相关的配置 代码(配置文件)application.properties 配置 Kafka 及对应的 属性处理类 配置Kafka spring.kafka.* 开头的配置属性,这些属性将由…...

【蓝桥杯选拔赛真题61】python偶数平方 第十五届青少年组蓝桥杯python 选拔赛比赛真题解析
目录 python偶数平方 一、题目要求 1、编程实现 2、输入输出...

智能语音识别源码系统+语义理解+对话管理+语音合成 带完整的搭建教程
人工智能技术的不断发展,智能语音识别技术逐渐成为人们日常生活和工作中不可或缺的一部分。然而,目前市场上的智能语音识别产品大多存在一定的局限性,如识别率不高、功能单一等。为了解决这些问题,罗峰给大家分享一款基于智能语音…...

cdh6.3.2的hive配udf
背景 大数据平台的租户要使用udf,他们用beeline连接, 意味着要通过hs2,但如果有多个hs2,各个hs2之间不能共享,需要先把文件传到hdfs,然后手动在各hs2上create function。之后就可以永久使用了,…...

在DevEco开发工具中,使用Previewer预览界面中的UI组件
1、在DevEco工具中,点击并展开PreViewer预览器 2、在PreViewer预览器中,点击Tt按钮(Inspector)切换至组件查看模式 3、在组件查看模式下选择组件,代码呈现选中状态,右侧呈现组件树,右下方呈现组…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...

【Python】 -- 趣味代码 - 小恐龙游戏
文章目录 文章目录 00 小恐龙游戏程序设计框架代码结构和功能游戏流程总结01 小恐龙游戏程序设计02 百度网盘地址00 小恐龙游戏程序设计框架 这段代码是一个基于 Pygame 的简易跑酷游戏的完整实现,玩家控制一个角色(龙)躲避障碍物(仙人掌和乌鸦)。以下是代码的详细介绍:…...

【力扣数据库知识手册笔记】索引
索引 索引的优缺点 优点1. 通过创建唯一性索引,可以保证数据库表中每一行数据的唯一性。2. 可以加快数据的检索速度(创建索引的主要原因)。3. 可以加速表和表之间的连接,实现数据的参考完整性。4. 可以在查询过程中,…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南
精益数据分析(97/126):邮件营销与用户参与度的关键指标优化指南 在数字化营销时代,邮件列表效度、用户参与度和网站性能等指标往往决定着创业公司的增长成败。今天,我们将深入解析邮件打开率、网站可用性、页面参与时…...

网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...

C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
tomcat指定使用的jdk版本
说明 有时候需要对tomcat配置指定的jdk版本号,此时,我们可以通过以下方式进行配置 设置方式 找到tomcat的bin目录中的setclasspath.bat。如果是linux系统则是setclasspath.sh set JAVA_HOMEC:\Program Files\Java\jdk8 set JRE_HOMEC:\Program Files…...
Python竞赛环境搭建全攻略
Python环境搭建竞赛技术文章大纲 竞赛背景与意义 竞赛的目的与价值Python在竞赛中的应用场景环境搭建对竞赛效率的影响 竞赛环境需求分析 常见竞赛类型(算法、数据分析、机器学习等)不同竞赛对Python版本及库的要求硬件与操作系统的兼容性问题 Pyth…...