【前端】重构,有品位的代码 06── 重新组织数据

开发 前端
变量在代码中有着不同的用途,而有些用途毁导致临时变量被多次赋值,比如:循环语句中的变量以及结果收集变量(通过整个函数运算构成的值)。

[[409049]]

本文转载自微信公众号「前端万有引力」,作者一川。转载本文请联系前端万有引力公众号。

重新组织数据

常用的重新组织数据方式有:

  • 拆分变量
  • 字段改名
  • 以查询取代派生变量
  • 将引用对象改为值对象
  • 将值对象改为引用对象

1. 拆分变量

变量在代码中有着不同的用途,而有些用途毁导致临时变量被多次赋值,比如:循环语句中的变量以及结果收集变量(通过整个函数运算构成的值)。当然,还有许多变量只被赋值一次,用于保存冗长代码的运算结果,如果其承担多个责任(被赋值多次),那么就意味着需要对其进行拆分为多个单独责任的变量。

其实,就是在待分解变量的声明及其初次被赋值处,修改其名称,尽量将其变量声明设置为不可修改(其实就是使用const)。以该变量的第二次赋值动作为界,修改此时对该变量的所有引用,让其引用新变量。

原始代码:

  1. let height = 2, width = 3; 
  2. let temp = 4 * ( height + width); 
  3. console.log(temp); 
  4.  
  5. temp = height * width; 
  6. console.log(temp); 

重构代码:

  1. const height = 2, width = 3; 
  2. const perimeter = 4 * ( height + width); 
  3. console.log(perimeter); 
  4.  
  5. const area = height * width; 
  6. console.log(area); 

2. 字段改名

对于程序中广泛使用的记录结构,数据结构有助于阅读理解代码逻辑,其字段的命名显得格外重要。数据结构作用无非就是让代码更加简洁有条理,但事实上随着时间的推移,我们对代码的理解更加透彻,此时就会对于某些字段根据作用和业务进行改名。

来看看如何对字段进行改名,首先判断当前记录的作用域的范围,当其作用域小时可以直接修改所有该字段的代码。当然如果作用域范围大时,可以先对记录进行封装,在对象内部对私有字段进行改名,并对应调整内部访问该字段的函数。

原始代码:

  1. class User
  2.   constructor(data){ 
  3.     this._name = data.name
  4.     this._age = data.age; 
  5.   } 
  6.   get name(){ 
  7.     return this._name; 
  8.   } 
  9.   set name(newName){ 
  10.     this._name = newName; 
  11.   } 
  12.   get age(){ 
  13.     return this._age; 
  14.   } 
  15.   set age(newAge){ 
  16.     this._age = newAge; 
  17.   } 
  18. const yichuan = new User({name:"yichuan",age:18}); 

重构代码:

  1. class User
  2.   constructor(data){ 
  3.     this._title = data.title; 
  4.     this._age = data.age; 
  5.   } 
  6.   get title(){ 
  7.     return this._title; 
  8.   } 
  9.   set title(newTitle){ 
  10.     this._name = newTitle; 
  11.   } 
  12.   get age(){ 
  13.     return this._age; 
  14.   } 
  15.   set age(newAge){ 
  16.     this._age = newAge; 
  17.   } 

是不是很简单,就是对应的改变字段名字而已。

3. 以查询取代派生变量

要知道数据可变时软件犯错的源头,对数据的修改常导致代码各部分耦合,即在某处进行修改后,却对另外一处造成意想不到的灾难。当然,完全消灭可变数据这是不现实的,所以应该将可变数据的作用域缩小到可控制范围内。

计算能够清晰地表达数据的含义,能够最大化避免源数据修改时忘更新派生变量的情况。有些变量很容易随时被计算,如果能够将其消除此变量,那么也就朝着消除数据可变性更进一步。如果计算的源数据是不可变的,也可以强制计算得到的结果是不可变的,这样就不必消除计算得到的派生变量。因此,可以根据源数据生成新数据结构的变换操作保持不变,即使已经将其替换为计算操作。

看看具体例子,其原始代码如下:

  1. get discountedTotal(){ 
  2.   return this._discountedTotal; 
  3. set discountedTotal(discount){ 
  4.   const old = this._discount; 
  5.   this._discount = discount; 
  6.   this._discountedTotal += old - discount; 

重构代码:

  1. get discountedTotal(){ 
  2.   return this._baseTotal - this._discount; 
  3. set discountedTotal(discount){ 
  4.   this._discount = discount; 

4. 将引用对象改为值对象

在将一个对象嵌入到另一个对象时,位于内部的这个对象被称为引用对象,亦可称为值对象。当然两者最明显差异在于如何更新内部对象的属性:如果将内部对象视为引用对象,在更新其属性时可以保留原对象不动,只更新内部对象的属性;如果将内部对象视为值对象,可以替换整个内部对象,对新对象可以设置新的属性值,

在实际操作中,得先检查重构目标是否是不可变对象,或者是否可修改不可变对象,再逐步去除所有设置函数。提供一个基于值的相等性判断函数,在其中使用对象的字段。

原始代码:

  1. class Product{ 
  2.   applyDiscount(arg){ 
  3.     this._price.aount -= arg; 
  4.   } 

重构代码:

  1. class Product{ 
  2.   applyDiscount(arg){ 
  3.     this._price = new Money(this._price.amount - arg, this._price.currency) 
  4.   } 

5. 将值对象改为引用对象

在数据结构中有可能包含多个记录,这些记录都关联到同个逻辑数据结构。同份数据复制多次可能造成困扰,因为会导致内存占用问题,会导致性能问题。如果共享数据需要更新,可以将多份数据副本变成单一引用,可以将数据修改反映到变化中。

在为相关对象创建一个仓库,确保构造函数可以找到关联对象的正确实例,修改宿主对象的构造函数,令其从仓库中获取关联对象。

  1. // 原始代码 
  2. let customer = new Customer(data); 
  3. // 重构代码 
  4. let customer = customerRespository.get(data.id); 

小结

在本文中,主要介绍了如何重新组织数据,可以将代码中的数据结构进行改善。

参考文章

 

《重构──改善既有代码的设计(第2版)》

 

责任编辑:武晓燕 来源: 前端万有引力
相关推荐

2021-07-01 08:28:24

前端搬移特性开发技术

2021-08-03 08:13:48

重构API代码

2021-07-10 14:22:24

前端代码条件逻辑

2013-09-16 10:57:59

苹果世界

2022-05-06 15:24:15

数字化转型市场化企业

2019-09-27 09:57:09

大数据机器学习神经网络

2020-12-08 06:20:49

前端重构Vue

2013-06-09 10:37:14

架构框架

2021-10-18 11:42:23

数据系统权衡

2012-07-27 10:30:12

重构

2022-08-08 13:24:28

整洁架构架构前端

2019-02-18 16:21:47

华为代码重构

2011-08-16 09:47:58

编程

2020-11-17 05:52:08

数据中心自动化数据中心

2022-12-26 00:02:24

重构代码软件

2019-04-03 08:10:17

代码架构信息

2023-10-20 08:04:34

系统重构实践

2021-08-01 22:35:16

Vscode开发编辑器

2023-02-27 07:40:00

系统重构前端

2024-02-22 10:27:00

Python开发
点赞
收藏

51CTO技术栈公众号