2016年5月22日 星期日

[book] The effective engineer

Part 1: Adopt the Right Mindsets



chapter1: Focus on High-Leverage Activities

  1. 要學會衡量什麼各個事情的價值 
  2. 做最有價值的事情

chapter2: Optimize for learning

  1. 做你能掌控的事情
  2. 加快你的學習速度
  3. 找到好的環境能讓你成長更快的
  4. 多多善用工作上的資源 來提升你的技術, 跟團隊最強的工程師學西
  5. 再工作之外學習, 社群通常都是對此技術很有興趣 且以此為樂的人
  6. 永遠都在學習
    1. 學習新語言 新框架
    2. 投資再高需求的語言上
    3. 讀書
    4. 參加研討會 報告
    5. opensource
    6. 讀好的blog
    7. write to teach
    8. side project
    9. 追求你愛的

chapter3 Prioritize Regularly

  1. 寫下todo list
  2. 做todo list中 最有價值的事情
  3. 做重要 但不急的事情
  4. 減少context switches
  5. 做一個if的plan, ex: 如果有突然二十分鐘 我會做什麼事情
  6. 養成排優先順序的習慣

Part 2: Execute, Execute, Execute


chapter4:  Invest in Iteration Speed 

  1. 轉換越快 學的越多
  2. 投資再工具上 ex 開發環境 工具
  3. 最佳化的你的debug 流程
  4. 讓你的開發環境最佳化
  5. 整體性的觀點來看你的開發流程 有沒有可以改善的地方 包含團隊合作

chapter5: 「Measure What You Want to Improve」

  1. 量測你的進步
  2. 找出會讓你最有效率的衡量模式
  3. 找出你系統的衡量方式 怎樣是好
  4. 知道你的數字
  5. 資料的正確性很重要

chapter6: 「Validate Your Ideas Early and Often」 

  1. 越快的驗證你的想法 會減少浪費資源
  2. 用小驗證的方式來取代大更新, 常常驗證 常常更新
  3. 使用A/B testing來驗證你的產品
  4. 當做自己的專案時 也是要想辦法得到別人常常的建議
  5. 一直要有回應來驗證你的想法

chapter7: 「Improve Your Project Estimation Skills」

  1. 估時程時 將每個專案切成小工作項目 再結合起來計算
  2. 要留buffer再不確定的事情上面
  3. 建立可以被測量的里程碑
  4. 最優先做風險最高的事情
  5. 知道加班的限制性

Part 3: Build Long-Term Value


chapter 8: 「Balance Quality with Pragmatism」 

  1. code review
  2. 投資時間在建立好的軟體抽象化 來簡化複雜的問題
  3. 自動化測試
  4. 管好你的技術債

chapter 9: Minimize Operational Burden

     1.先做簡單的事情, 能夠重覆使用的套件 就使用 專注再自己業務的部份
     2.錯誤要及早知道, 然後直接再log指出錯誤的地方
     3.如果當錯誤的時候 要自動化去處理掉, 多想幾次, 是不是會造成之後永遠不知道為什麼會錯
     4.多使用idempotence and reentrancy, 會讓你之後再retry錯誤的時候更單純
     5.計畫模擬錯誤的情況


chapter 10 Invest in Your Team’s Growth

  1. 讓你身邊的人也更成功, 不同階級的工程師 會讓身邊更多的人也更進步
  2. 找到優秀的人 是最高priority
  3. 投資時間在新人剛進來的時候 mentoring制度
  4. 建立大家共有的程式 大家都可以維護互相的程式
  5. 讓大家更透明化, 討論目前工作的難處 好處 建立大家的知識庫
  6. 建立好的工程師文化
 

2016年5月15日 星期日

API命名


語意是變數名稱中最重要的一部份,”published”, “unpublished” 意味著產品的狀態,所以最簡單最簡單的 pattern,就是 Adj. + N. 就可以是一個清楚的變數名稱。

單數複數表示也很重要,當我們採用複數命名,其意味著該變數很可能是一個 array 類型、collection 類型、traversable 類型的資料。

  • get => 取得否些屬性會數值
  • set => 和get一樣 不該用在資料庫操作
  • query => api操作 帶參數
  • do => 沒啥意義, 可用update, _update,  _update的scope通常為private
  • fetch / store => 同query, 但fetch通常不帶有複雜的操作
  • build => 建置需要的資料, 還沒那麼明確, 建置資料 準備給其他的東西用 但還沒到資料庫
  • create => 建置到資料庫, 有明確的目標和範圍
  • new => 初始化
  • remove => 從資料集中移除項目 移除關連
  • delete => 刪除 實體資料刪除
  • traverse => 處理tree
 

2016年5月10日 星期二

解釋 Cookie 的特性



Cookie 的運作是這樣的:
  1. Server 端回應給 Browser 一個或多個 "Set-Cookie" HTTP Header
  2. Client 端 ( Browser ) 接收到 Set-Cookie 指令時,會將 Cookie 的名稱與值儲存在 Browser 的 Cookie 存放區,並記錄該 Cookie 隸屬的網域、網址路徑、過期時間、是否為安全連線
  3. 當 Browser 再次發出 HTTP Request 指令到 Server 時,就會比對目前在 Browser 內的 Cookie 存放區有沒有「該網域」、「該目錄」、「過期時間尚未過期」且「是否為安全連線」的 Cookie,如果有的話就會包含在 HTTP Request 指令的 "Cookie" Header 中。 

2016年5月7日 星期六

immediately-invoked-function-expression


立即函是是Javascript中一種可以立即執行的函式,其本質其實是個函式表示式。下面程式碼代表著一個簡單的立即函式。

(function(){
  // my special code
}());
其中的括號()代表的就是立刻執行該函式。在語法上,括號()也可以被放到左括號)外面,像是這樣。

(function(){
  // my special code
})();

1.全域變數的減少:

   寫程式難免會用到一些變數,但要避免變數暴露在全域之中,唯一的方式就是把它包裹在函式之中,或許你以前也有減少全域變數的觀念,所以你把程式碼寫在一個函式中,然後再呼叫它。現在你其實可以不需要這樣做,因為有立即函式的存在,所以你可以把程式碼包裹在立即函式中,然後放在它該出現的位置,在也不用看到一個init()(譬如說啦..)的呼叫,然後要拉到程式碼最下方去看這init()在做啥了。

2.全域變數區域化:

   看到JQuery的範例了嗎,他把全域變數window當成參數傳遞給立即函式中,因此在函式中,window就變成了區域變數。這樣做是因為Javascript在看到變數時會先查找區域變數,然後再查找全域變數,因此全域變數變成區域變數在效率上有些微的提升。另外也可以最小化變數名稱,一般Javascript最小化的程式並不會對全域變數進行壓縮(因為不安全),但區域變數就可以。因此全域變數區域化可以減少檔案的大小。當然你也可以自己來最小化。

(function( w, u) {
....

})( window );  

understanding-javascript-function-prototype-bind

understanding-javascript-function-prototype-bind

var foo = {
    x: 3
}

var bar = function(){
    console.log(this.x);
}

bar(); // undefined

var boundFunc = bar.bind(foo);

boundFunc(); // 3


bind something to as this 

JavaScript-Scoping-and-Hoisting

http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html


Function declarations and variable declarations are always moved (“hoisted”) invisibly to the top of their containing scope by the JavaScript interpreter. Function parameters and language-defined names are, obviously, already there. This means that code like this:

function foo() {
    bar();
    var x = 1;
}
is actually interpreted like this:

function foo() {
    var x;
    bar();
    x = 1;
}

How to Code With This Knowledge

Now that you understand scoping and hoisting, what does that mean for coding in JavaScript? The most important thing is to always declare your variables with a var statement. I strongly recommend that you have exactly one var statement per scope, and that it be at the top. If you force yourself to do this, you will never have hoisting-related confusion. However, doing this can make it hard to keep track of which variables have actually been declared in the current scope. I recommend using JSLint with the onevar option to enforce this. If you’ve done all of this, your code should look something like this:

/*jslint onevar: true [...] */
function foo(a, b, c) {
    var x = 1,
        bar,
        baz = "something";


}

2016年5月5日 星期四

writing-a-domain-specific-language-in-ruby


how to write domain-specific language in ruby

example:
Smokestack.define do
  factory User do
    name "Gabe BW"
    pet_name "Toto"
  end
end

user = Smokestack.build(User)
puts user.name == 'Gabe BW'  # true
puts user.pet_name == 'Toto' # true

other_user = Smokestack.build(User, name: "Bob")
puts other_user.name == 'Bob'      # true
puts other_user.pet_name == 'Toto' # true

how it works?

module Smokestack
  @registry = {}

  def self.registry
    @registry
  end

  def self.define(&block)
    definition_proxy = DefinitionProxy.new
    definition_proxy.instance_eval(&block)
  end

  def self.build(factory_class, overrides = {})
    instance = factory_class.new
    factory = registry[factory_class]
    attributes = factory.attributes.merge(overrides)
    attributes.each do |attribute_name, value|
      instance.send("#{attribute_name}=", value)
    end
    instance
  end
end

class DefinitionProxy
  def factory(factory_class, &block)
    factory = Factory.new
    factory.instance_eval(&block)
    Smokestack.registry[factory_class] = factory
  end
end

class Factory < BasicObject
  def initialize
    @attributes = {}
  end

  attr_reader :attributes

  def method_missing(name, *args, &block)
    @attributes[name] = args[0]
  end
end


三個主要的物件
module Smokestack => 記錄所有的, 用@registry 來記錄目前所有的定義(definition_proxy), build就是實際產生一個需要的instance
class DefinitionProxy => 定義 factory方法, 用instance_eval打開每一個factory, 再傳入需要做的block, 之後透過smokestack來registry factory

class Factory < BasicObject => 實際的每一個factory要做什麼, 用method_missing來實現