iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 3
2

良好程式碼的優點大同小異。
不好的程式碼的糙點卻各有巧妙之處。

一開始學習寫程式,有個還不會寫 function 的過程,常常出現一個 main 到底的程式碼。

//有一些變數宣告
var words = 'hello world';

//有一些程式碼執行
console.log(words);

後來,學了 function 就學會這樣的寫法

//有一些變數宣告
var words = 'hello world';

//有一些程式碼執行
function printHello() {
  console.log(words);
}

printHello();

然後,覺得這很棒!!

相信很多人看到這個小小的例子,都可以看出一些糙點。
但是當它變成了大型程式,就看不出糙點了

看一個真實案例改編而成的糙 code

它原本不是 js 的程式,為了避免侵權的問題,在此改寫成 js 的 code。
不影響它的糙點!

var gIniPath = `./config/app.ini`);
var gLogFile;
var gIniInfo;
var gIndicatorSettingDic = Map();

class myClass {
  class IniInfo {/* ... */}
  constructor () {
    if (gIniInfo.CheckRepeatModule) {
      // 避免重複執行
    }
    
    gLogFile = new LogFile();
    gLogFile.readFile(gIniPath, "MsgLog");
    gIniInfo = new IniInfo();
    
    this.Exit = function () {
      gAppEventBus = null;
      gLogFile = null;
      gIniInfo = null;
    }
  }
  
  print () {
    for (let [ key, val ] of gIndicatorSettingDic.entries()) {
        console.log(key + " = " + val)
    }
  }
}

myClass 裡,其實並沒有真正做到模組化。這些 「g開頭」的全域變數,其實並沒有需要成為全域與別人「共用」(或「不小心會誤用」)

國王的心態

大多這麼寫的工程師,心裡面會想著「用起來方便呀」、「隨叫隨到的變數」、「不用思考怎麼把它傳進來」....等。

其實,很不好!

DX[1] 很差

製造痛點!!
對寫 code 的人很開心,對用 code 的人不開心呀!!

var myObject1 = new myClass()
// 你知道它載入的是什麼設定檔嗎?
var myObject2 = new myClass()
myObject1.print();
myObject2.print();
// 你知道印出來會不會是同樣的內容嗎?
gIndicatorSettingDic = null;

myObject1.print();
myObject2.print();
// 你知道被清空了嗎?

以語法來說,是封裝不良的問題。

應該這樣思考

  • myClass 這個要載著什麼樣的概念,它會有什麼行為?
  • 在使用 method 時,需要先知道什麼嗎?不知的話會出錯嗎?

以此例,myClass 需要載入 .ini 檔。

var myObject1 = new myClass(`./config/app.ini`);
var myObject2 = new myClass(`./config/app.ini`);

這樣就會知道,此物件要吃某個 config 檔。
又或者建構式提供一組預設值,再另外吃 config 也行

var myObject1 = new myClass();
myObject1.setConfig(`./config/app.ini`);
var myObject2 = new myClass();
myObject2.setConfig(`./config/app.ini`);

這樣一來,使用這一個 class 的開發者,就不會因為不良耦合的關係,心中浮現一句這樣的話

「誰知道!? 誰!? 誰呀!?」
「誰!?」

static 要小心使用

有些程式語言可以將 static 用在變數上,讓它的生命週期跨越生死,永續保存。
這個要小心,不要濫用!!

以上述的 js 程式碼為例。
如果將所有的全域變數,搬到 myClass 裡,然後宣告成 static 而且,在 destructorExit 時,將這些變數變成 null ,就是原本「糙味加倍」的樣子

原因在於,物件本身的生命週期可以利用,將變數變成區域變數,就不用擔心跨 myClass 物件之間存取相同的參考資料, myClass 不用時,也只需要靠垃圾收集即可。

[1]: 工程師心中最軟的一塊:談前端開發者體驗(Developer Experience)


上一篇
曝露過多的複雜性
下一篇
糙 code 與他們的產地 - if 的判斷式
系列文
可不可以不要寫糙 code30

1 則留言

0
catkitchen721
iT邦新手 5 級 ‧ 2018-10-30 13:40:22

實用,推

我要留言

立即登入留言