新聞中心
本文轉(zhuǎn)載自微信公眾號(hào)「前端萬(wàn)有引力」,作者一川。轉(zhuǎn)載本文請(qǐng)聯(lián)系前端萬(wàn)有引力公眾號(hào)。

我們提供的服務(wù)有:網(wǎng)站制作、網(wǎng)站設(shè)計(jì)、微信公眾號(hào)開(kāi)發(fā)、網(wǎng)站優(yōu)化、網(wǎng)站認(rèn)證、東寧ssl等。為超過(guò)千家企事業(yè)單位解決了網(wǎng)站和推廣的問(wèn)題。提供周到的售前咨詢(xún)和貼心的售后服務(wù),是有科學(xué)管理、有技術(shù)的東寧網(wǎng)站制作公司
重新組織數(shù)據(jù)
常用的重新組織數(shù)據(jù)方式有:
- 拆分變量
- 字段改名
- 以查詢(xún)?nèi)〈缮兞?/li>
- 將引用對(duì)象改為值對(duì)象
- 將值對(duì)象改為引用對(duì)象
1. 拆分變量
變量在代碼中有著不同的用途,而有些用途毀導(dǎo)致臨時(shí)變量被多次賦值,比如:循環(huán)語(yǔ)句中的變量以及結(jié)果收集變量(通過(guò)整個(gè)函數(shù)運(yùn)算構(gòu)成的值)。當(dāng)然,還有許多變量只被賦值一次,用于保存冗長(zhǎng)代碼的運(yùn)算結(jié)果,如果其承擔(dān)多個(gè)責(zé)任(被賦值多次),那么就意味著需要對(duì)其進(jìn)行拆分為多個(gè)單獨(dú)責(zé)任的變量。
其實(shí),就是在待分解變量的聲明及其初次被賦值處,修改其名稱(chēng),盡量將其變量聲明設(shè)置為不可修改(其實(shí)就是使用const)。以該變量的第二次賦值動(dòng)作為界,修改此時(shí)對(duì)該變量的所有引用,讓其引用新變量。
原始代碼:
- let height = 2, width = 3;
- let temp = 4 * ( height + width);
- console.log(temp);
- temp = height * width;
- console.log(temp);
重構(gòu)代碼:
- const height = 2, width = 3;
- const perimeter = 4 * ( height + width);
- console.log(perimeter);
- const area = height * width;
- console.log(area);
2. 字段改名
對(duì)于程序中廣泛使用的記錄結(jié)構(gòu),數(shù)據(jù)結(jié)構(gòu)有助于閱讀理解代碼邏輯,其字段的命名顯得格外重要。數(shù)據(jù)結(jié)構(gòu)作用無(wú)非就是讓代碼更加簡(jiǎn)潔有條理,但事實(shí)上隨著時(shí)間的推移,我們對(duì)代碼的理解更加透徹,此時(shí)就會(huì)對(duì)于某些字段根據(jù)作用和業(yè)務(wù)進(jìn)行改名。
來(lái)看看如何對(duì)字段進(jìn)行改名,首先判斷當(dāng)前記錄的作用域的范圍,當(dāng)其作用域小時(shí)可以直接修改所有該字段的代碼。當(dāng)然如果作用域范圍大時(shí),可以先對(duì)記錄進(jìn)行封裝,在對(duì)象內(nèi)部對(duì)私有字段進(jìn)行改名,并對(duì)應(yīng)調(diào)整內(nèi)部訪(fǎng)問(wèn)該字段的函數(shù)。
原始代碼:
- class User{
- constructor(data){
- this._name = data.name;
- this._age = data.age;
- }
- get name(){
- return this._name;
- }
- set name(newName){
- this._name = newName;
- }
- get age(){
- return this._age;
- }
- set age(newAge){
- this._age = newAge;
- }
- }
- const yichuan = new User({name:"yichuan",age:18});
重構(gòu)代碼:
- class User{
- constructor(data){
- this._title = data.title;
- this._age = data.age;
- }
- get title(){
- return this._title;
- }
- set title(newTitle){
- this._name = newTitle;
- }
- get age(){
- return this._age;
- }
- set age(newAge){
- this._age = newAge;
- }
- }
是不是很簡(jiǎn)單,就是對(duì)應(yīng)的改變字段名字而已。
3. 以查詢(xún)?nèi)〈缮兞?/h3>
要知道數(shù)據(jù)可變時(shí)軟件犯錯(cuò)的源頭,對(duì)數(shù)據(jù)的修改常導(dǎo)致代碼各部分耦合,即在某處進(jìn)行修改后,卻對(duì)另外一處造成意想不到的災(zāi)難。當(dāng)然,完全消滅可變數(shù)據(jù)這是不現(xiàn)實(shí)的,所以應(yīng)該將可變數(shù)據(jù)的作用域縮小到可控制范圍內(nèi)。
計(jì)算能夠清晰地表達(dá)數(shù)據(jù)的含義,能夠最大化避免源數(shù)據(jù)修改時(shí)忘更新派生變量的情況。有些變量很容易隨時(shí)被計(jì)算,如果能夠?qū)⑵湎俗兞浚敲匆簿统龜?shù)據(jù)可變性更進(jìn)一步。如果計(jì)算的源數(shù)據(jù)是不可變的,也可以強(qiáng)制計(jì)算得到的結(jié)果是不可變的,這樣就不必消除計(jì)算得到的派生變量。因此,可以根據(jù)源數(shù)據(jù)生成新數(shù)據(jù)結(jié)構(gòu)的變換操作保持不變,即使已經(jīng)將其替換為計(jì)算操作。
看看具體例子,其原始代碼如下:
- get discountedTotal(){
- return this._discountedTotal;
- }
- set discountedTotal(discount){
- const old = this._discount;
- this._discount = discount;
- this._discountedTotal += old - discount;
- }
重構(gòu)代碼:
- get discountedTotal(){
- return this._baseTotal - this._discount;
- }
- set discountedTotal(discount){
- this._discount = discount;
- }
4. 將引用對(duì)象改為值對(duì)象
在將一個(gè)對(duì)象嵌入到另一個(gè)對(duì)象時(shí),位于內(nèi)部的這個(gè)對(duì)象被稱(chēng)為引用對(duì)象,亦可稱(chēng)為值對(duì)象。當(dāng)然兩者最明顯差異在于如何更新內(nèi)部對(duì)象的屬性:如果將內(nèi)部對(duì)象視為引用對(duì)象,在更新其屬性時(shí)可以保留原對(duì)象不動(dòng),只更新內(nèi)部對(duì)象的屬性;如果將內(nèi)部對(duì)象視為值對(duì)象,可以替換整個(gè)內(nèi)部對(duì)象,對(duì)新對(duì)象可以設(shè)置新的屬性值,
在實(shí)際操作中,得先檢查重構(gòu)目標(biāo)是否是不可變對(duì)象,或者是否可修改不可變對(duì)象,再逐步去除所有設(shè)置函數(shù)。提供一個(gè)基于值的相等性判斷函數(shù),在其中使用對(duì)象的字段。
原始代碼:
- class Product{
- applyDiscount(arg){
- this._price.aount -= arg;
- }
- }
重構(gòu)代碼:
- class Product{
- applyDiscount(arg){
- this._price = new Money(this._price.amount - arg, this._price.currency)
- }
- }
5. 將值對(duì)象改為引用對(duì)象
在數(shù)據(jù)結(jié)構(gòu)中有可能包含多個(gè)記錄,這些記錄都關(guān)聯(lián)到同個(gè)邏輯數(shù)據(jù)結(jié)構(gòu)。同份數(shù)據(jù)復(fù)制多次可能造成困擾,因?yàn)闀?huì)導(dǎo)致內(nèi)存占用問(wèn)題,會(huì)導(dǎo)致性能問(wèn)題。如果共享數(shù)據(jù)需要更新,可以將多份數(shù)據(jù)副本變成單一引用,可以將數(shù)據(jù)修改反映到變化中。
在為相關(guān)對(duì)象創(chuàng)建一個(gè)倉(cāng)庫(kù),確保構(gòu)造函數(shù)可以找到關(guān)聯(lián)對(duì)象的正確實(shí)例,修改宿主對(duì)象的構(gòu)造函數(shù),令其從倉(cāng)庫(kù)中獲取關(guān)聯(lián)對(duì)象。
- // 原始代碼
- let customer = new Customer(data);
- // 重構(gòu)代碼
- let customer = customerRespository.get(data.id);
小結(jié)
在本文中,主要介紹了如何重新組織數(shù)據(jù),可以將代碼中的數(shù)據(jù)結(jié)構(gòu)進(jìn)行改善。
參考文章
《重構(gòu)──改善既有代碼的設(shè)計(jì)(第2版)》
網(wǎng)站名稱(chēng):【前端】重構(gòu),有品位的代碼06──重新組織數(shù)據(jù)
標(biāo)題URL:http://fisionsoft.com.cn/article/dpscjjh.html


咨詢(xún)
建站咨詢(xún)
