2019年7月23日 星期二

Reuse, but don't make a huge function

  • The concept of DRY is super simple - do not duplicate codes if there are already in the program. The basic practice is using a function to do a particular action and let other places call the function if they need.
      // bad
      const name1 = 'Bob'
      const msg1 = 'Hi'
      console.log(`${name1} says: ${msg1}`)
    
      const name2 = 'Tom'
      const msg2 = `How's it going?`
      console.log(`${name2} says: ${msg2}`)
    
      // good
      function say(name, message) {
        console.log(`${name} says: ${message}`)
      }
    
      say('Bob', 'Hi')
      say('Tom', `How's it going?`)
    
  • However, once the requirement changed and we modify the function, of course, all function calls will be affected. That's good we save time.
      function say(from, to, message) {
        console.log(`${from} says ${to}: ${message}`)
      }
    
      say('Bob', 'John', 'Hi')
      say('Tom', 'Peter', `How's it going?`)
    
  • It is very common that we use parameters as inputs to let a function deal with for different situations.
      function say(from, to, message) {
        if (to !== null && to !== undefined) {
          console.log(`${from} says ${to}: ${message}`)
        } else {
          console.log(`${from} says: ${message}`)
        }
      }
    
      say('Bob', 'John', 'Hi')
      say('Tom', null, `How's it going?`)
    
  • You know, the requirement might change many times because customers are indecisive. Even if they don't, we still have to do refactoring in order to have better code quality. That means we might change codes.
      function say(from, to, message, isQuestion) {
        const ending = isQuestion ? '?' : '.'
        if (to !== null && to !== undefined) {
          console.log(`${from} says ${to}: ${message}${ending}`)
        } else {
          console.log(`${from} says: ${message}${ending}`)
        }
      }
    
      say('Bob', null, 'Hi', false)
      say('Tom', 'Peter', `How's it going`, true)
    
  • You will realize that functions have more complex parameters and conditions are very hard to modify. It calls "high coupling" if there are too many places rely on a heavy code.
      // the combinations you need to test in order to make sure your function works:
      say('name', null, 'message', false)
      say('name', 'name', 'message', false)
      say('name', null, 'message', true)
      say('name', 'name', 'message', true)
    
      // the combinations you may not expect that will ruin your function:
      say(null, 'name', 'message', false)
      say('name', 'name', null, true)
    
  • Therefore, when you are trying to DRY your code, be careful that don't put too many codes into one function. The function will be super complex and hard to maintain. It may be a good idea to have small functions instead.
      // there are actually 4 scenarios, so it may be a good idea to have 4 functions
      // new function names are more semantic
      // there are no magical boolean flag and optional parameters (reduce parameter mistakes)
      // we get rid of if conditions (reduce the complexity)
      // once one of the functions changed, we won't affect other functions
    
      function talk(name, message) {
        console.log(`${name} says: ${message}.`)
      }
    
      function askQuestion(name, message) {
        console.log(`${name} says: ${message}?`)
      }
    
      function talkToSomeone(name, someone, message) {
        console.log(`${name} says to ${someone}: ${message}.`)
      }
    
      function askQuestionToSomeone(name, someone, message) {
        console.log(`${name} says to ${someone}: ${message}?`)
      }
    
      talk('Bob', 'Hi')
      askQuestion('Tom', `How's it going`)
      talkToSomeone('Bob', 'John', 'Hi')
      askQuestionToSomeone('Tom', 'Peter', `How's it going`)
    
  • This example is overly simple, and the naming actually sucks, but I hope I give you a general idea of how to organize your functions.

2017年7月1日 星期六

一為全 全為一

資料庫如果面臨 資料具有狀態及歷程特性 且 需要因特定狀況下取消/復原狀態 或 差異比對

每次狀態變更 都新增一筆全新的紀錄 或許 比重複修改狀態欄位 來得簡單

這其實就是 前端 單向資料流 的概念嘛

2017年6月13日 星期二

Javascript 用雙波浪號 ~~ 來 屌炸天 轉型整數前請三思

Javascript 用雙波浪號 ~~ 來 屌炸天 轉型整數前請三思

tl;dr

曾幾何時看到別人 JS 寫雙波浪號 來把 string 轉型成 number 而且是整數

http://qa.helplib.com/84467

例如 ~~'123.456' = 123

其實效果跟 Math.floor('123.456') 一樣

某些瀏覽器可能用雙波浪寫法會快上一些

https://jsperf.com/tilde-vs-floor

然而 Number.MAX_SAFE_INTEGER 是 9007199254740991

照理來說 只要不超過這個數字 應該就沒事吧

事實上 只有 -2147483648 ~ 2147483648 範圍的值有作用

Bitwise operators treat their operands as a sequence of 32 bits (zeroes and ones), rather than as decimal, hexadecimal, or octal numbers. For example, the decimal number nine has a binary representation of 1001. Bitwise operators perform their operations on such binary representations, but they return standard JavaScript numerical values.
The numbers -2147483648 and 2147483647 are the minimum and the maximum integers representable through a 32bit signed number.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Bitwise_Operators

簡單來說只要值超過 2147483648 就 GG 啦

我已經不知多少專案用了這個寫法 祈禱他們都只會小於 2147483648

如果有不幸 我相信接手的人都足夠機智 可以突破盲腸

2015年2月25日 星期三

關於 Linq To Xml 抓不到 XElement 的問題

Linq To Xml 很強大 用來處理 XML 十分方便

但是下面這個 RSS feed 卻無法順利抓到 XElement

http://www.google.com.tw/alerts/feeds/09781140062556884779/15827306603345874523





說穿了沒什麼 就是它的 XName 實際上叫 "{http://www.w3.org/2005/Atom}entry" 而非 瀏覽器上看到的 "entry"

但是第一次遇到的當下肯定覺得

X! 之前這樣寫明明就可以抓到 怎麼現在不行

著實惱人

stackoverflow





參考寫法:

2015年1月1日 星期四

搞專案就是在打牌 改需求就是在變魔術

搞專案就是在打牌 改需求就是在變魔術

剋扈 : 給我把梅花 3 搓成 黑桃ㄟ死

PM : 對呀對呀

PG : 好的 您的 黑桃ㄟ死

剋扈 : 誰跟你要黑桃ㄟ死了 現在要同花順

PM : 對呀對呀

PG : 可是只有一張牌

剋扈 : 那是你家的事

PM : 對呀對呀

PG : ...