重构改善既有代码的设计-学习(三):重新组织数据

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) 

        一个数据结构中可能包含多个记录,而这些记录都关联到同一个逻辑数据结构。例如,我可能会读取一系列订单数据,其中有多条订单属于同一个顾客。遇到这样的共享关系时,既可以把顾客信息作为值对象来看待,也可以将其视为引用对象。如果将其视为值对象,那么每份订单数据中都会复制顾客的数据;而如果将其视为引用对象,对于一个顾客,就只有一份数据结构,会有多个订单与之关联。

        如果顾客数据永远不修改,那么两种处理方式都合理。把同一份数据复制多次可能会造成一点困扰,但这种情况也很常见,不会造成太大问题。过多的数据复制有可能会造成内存占用的问题,但就跟所有性能问题一样,这种情况并不常见。

        如果共享的数据需要更新,将其复制多份的做法就会遇到巨大的困难。此时我必须找到所有的副本,更新所有对象。只要漏掉一个副本没有更新,就会遭遇麻烦的数据不一致。这种情况下,可以考虑将多份数据副本变成单一的引用,这样对顾客数据的修改就会立即反映在该顾客的所有订单中。 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

外贸干货!社媒营销养号全攻略:10个必须知道的养号技巧

大家都知道&#xff0c;养号已经成为任何希望在WhatsApp、Facebook、TikTok等社交媒体平台上取得成功的跨境电商和营销人员的必备技能。在本文中&#xff0c;我们将深入探讨如何高效地进行养号&#xff0c;以及如何在海外社交媒体批量养号的过程中避免封号&#xff0c;确保你的…

Jenkins全局工具配置

目录 Jenkins全局工具全局工具配置Settings 文件配置Maven配置JDK配置Git配置 Jenkins全局工具 我们在安装了Jenkins之后&#xff0c;就可以开始使用Jenkins来进行一些自动化构建发布工作&#xff0c;但是开始之前我们还需要进行全局工具的配置&#xff0c;Jenkins全局工具配置…

如何使用 NFTScan API 检索 NFT 合约地址下 Transactions 数据

对于大多数人而言&#xff0c;获取某 NFT 合约地址下的全量交易记录是十分有挑战性的&#xff0c;不仅涉及到对区块链技术的深入了解以及使用相应的工具和资源&#xff0c;还需要处理区块链上的智能合约和交易数据&#xff0c;并将其与外部数据源进行整合分析。通常&#xff0c…

【UAT阶段】测试计划分享

前面我有分享UAT阶段注意事项&#xff0c;今天跟大家分享UAT测试计划包含哪些内容&#xff1a; 希望该计划能给大家在实际项目中有所帮助&#xff1b;

求职应聘找工作,你一定会遇到的人才测评

信息时代&#xff0c;越来越多的公司在招聘时引入了人才测评机制。企业和单位希望通过人才测评在广大的应聘者中&#xff0c;找到符合自己要求的人才。虽然很多应聘者能力和简历都比较出众&#xff0c;但却在最开始的人才测评中吃了亏。有的公司很看重人才测评结果。测评就相当…

WinSCP下载安装并实现远程SSH本地服务器上传文件

文章目录 1. 简介2. 软件下载安装&#xff1a;3. SSH链接服务器4. WinSCP使用公网TCP地址链接本地服务器5. WinSCP使用固定公网TCP地址访问服务器 1. 简介 ​ Winscp是一个支持SSH(Secure SHell)的可视化SCP(Secure Copy)文件传输软件&#xff0c;它的主要功能是在本地与远程计…

2017年认证杯SPSSPRO杯数学建模A题(第二阶段)安全的后视镜全过程文档及程序

2017年认证杯SPSSPRO杯数学建模 A题 安全的后视镜 原题再现&#xff1a; 汽车后视镜的视野对行车安全非常重要。一般来说&#xff0c;汽车的后视镜需要有良好的视野范围&#xff0c;以便驾驶员能够全面地了解车后方的道路情况。同时&#xff0c;后视镜也要使图像的畸变尽可能…

leetcode2859-计算K置位下标对应元素的和

题目链接 2859. 计算 K 置位下标对应元素的和 - 力扣&#xff08;LeetCode&#xff09; 解题思路 枚举nums的每一个下标i&#xff1b;统计i的二进制数的1的个数&#xff1b;累加满足bit_count(i) k的nums[i]; 难点&#xff0c;如何统计二进制中1的个数&#xff1f; 例题 …

postgresql12表膨胀解决(不锁表)

查看所有数据库占用磁盘空间 SELECTpg_database.datname AS "数据库名称",pg_size_pretty(pg_database_size(pg_database.datname)) AS "磁盘占用空间" FROMpg_database;发现有个数据库占用空间过大 查询库中所有表占用空间 SELECTtable_name,pg_size_…

固态硬盘优化设置

目录 前言&#xff1a; 关闭Windows Search 禁用系统保护&#xff08;不建议&#xff09; 不建议禁用系统保护原因 关闭碎片整理 提升固态硬盘速度 开启TRIM 合理使用固态硬盘的容量 正确关机 关闭开机自启 前言&#xff1a; 电脑配备固态硬盘就能一劳永逸吗&#…

字符金字塔(C语言刷题)

个人博客主页&#xff1a;https://blog.csdn.net/2301_79293429?typeblog 专栏&#xff1a;https://blog.csdn.net/2301_79293429/category_12545690.html 题目描述 请打印输出一个字符金字塔&#xff0c;字符金字塔的特征请参考样例 输入描述: 输入一个字母&#xff0c;保…

动态规划-96.不同的二叉搜索树

给定一个整数 n&#xff0c;求以 1 ... n 为节点组成的二叉搜索树有多少种&#xff1f; 思路 二叉搜索树特性&#xff1a;左子树的节点全部小于根节点&#xff0c;右子树的节点全部大于根节点 n3&#xff0c;则1&#xff0c;2&#xff0c;3轮流当根节点。 当1为根节点时&am…

一个前端搬砖“专家“的2023年度总结

23年年中的时候&#xff0c;我跟领导进行了一次沟通&#xff0c;讨论了下我后面应该在哪些地方深入。最后我就记得领导那句&#xff1a;缺少总结。 我发现我好像确实缺少总结&#xff0c;我平时会把遇到的问题&#xff0c;感觉值得记录的写在csdn里面&#xff0c;但是都只是问…

大数据信用查询系统能查到什么呢?

在金融助贷行业&#xff0c;大数据有叫大数据信用或者网贷大数据&#xff0c;在申贷的时候&#xff0c;想必大多数人都有听说过&#xff0c;很多人因为大数据不良的原因申贷被拒过&#xff0c;那大数据信用查询系统能查到什么呢?本文就简单为大家总结几点大数据信用查询的内容…

建议码住!2023年全球16大AI聊天工具汇总来啦

2023值得载入史册。这一年&#xff0c;全世界的AI技术迎来了重大突破&#xff0c;并从多个角度影响和改变了我们的生活和工作。 AI可以和你聊天、为你提供专业的法律建议、快速查找资料&#xff0c;还能帮助你制作视频、设计图片、制做PPT&#xff0c;甚至能够写代码、写小说、…

执行ping命令时提示ping: sendmsg: Operation not permitted

查看日志发现出现了大量的table full&#xff0c; dropping packet记录&#xff0c; 后上网查看资料发现是因为当前会话数已经满了&#xff0c;因此出现丢包现象。 这里需要说一下nf_conntrack nf_conntrack(在老版本的 Linux 内核中叫 ip_conntrack)是一个内核模块,用于跟踪一…

1005. K 次取反后最大化的数组和 - 力扣(LeetCode)

题目描述 给定一个整数数组 A&#xff0c;我们只能用以下方法修改该数组&#xff1a;我们选择某个索引 i 并将 A[i] 替换为 -A[i]&#xff0c;然后总共重复这个过程 K 次。&#xff08;我们可以多次选择同一个索引 i。&#xff09; 以这种方式修改数组后&#xff0c;返回数组可…

Oracal学习

Oracle是什么 是甲骨文公司的一款支持事务且吞吐量高的数据库特点&#xff1a; &#xff08;1&#xff09;支持多用户、大事务量的事务处理 &#xff08;2&#xff09;数据安全性和完整性控制 &#xff08;3&#xff09;支持分布式数据处理 &#xff08;4&#xff09;可移植性…

深度学习中RGB影像图的直方图均衡化python代码and对图片中指定部分做基于掩模的特定区域直方图均衡化

深度学习很重要的预处理步骤 就是需要对做直方图均衡化 其中主要分成灰度图以及RGB图的直方图均衡化 这俩的方法和代码不同 想要去看具体原理的朋友可以查看下面这篇博客的内容 写的很详细颜色直方图均衡化(https://www.cnblogs.com/wancy/p/17668345.html) 我们这个场景中会用…

Git 入门精讲

我们为什么要学习git&#xff1f; 就当下的发展而言&#xff0c;只要你从事开发就一定会接触git。作为最强大的分布式版本控制器&#xff0c;git 与 svn 有着本质上的区别。 Git是一种分布式版本控制系统&#xff0c;每个开发者都可以在本地维护完整的代码库&#xff0c;可以离…