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來實現 

2016年5月3日 星期二

JS 一定要放在Body 的最底部麼?聊聊瀏覽器的渲染機制


我們需要統一一下什麼叫我們經常掛在嘴邊的“頁面渲染出來了” ——指的是是“首屏顯示出來了”還是“頁面完整地加載好了”(後面統稱StepC) ? 
如果指的是首屏顯示出來了,那麼問題又來了:假設網頁首屏有圖片,這裡的“首屏”指的是“顯示了全部圖片的首屏”(後面統稱StepB)還是“沒有圖片的首屏”(後面統稱StepA)。

確定清楚“頁面渲染出來了” 指的是StepA、StepB、StepC 中的哪一個是非常關鍵的(雖然至今還沒有一個應聘者嘗試這麼做過),如果“頁面渲染出來了” 指的是StepC,那麼我的最後一問的答案是肯定的——script標籤不放在body底部不會拖慢頁面完整地加載好的時間。

瀏覽器的渲染過程

  1. Create/Update DOM And request css/image/js:瀏覽器請求到HTML代碼後,在生成DOM的最開始階段(應該是Bytes → characters後),並行發起css、圖片、js的請求,無論他們是否在HEAD裡。注意:發起js文件的下載request並不需要DOM處理到那個script節點,比如:簡單的正則匹配就能做到這一點,雖然實際上並不一定是通過正則:)。這是很多人在理解渲染機制的時候存在的誤區。
  2. Create/Update Render CSSOM:CSS文件下載完成,開始構建CSSOM
  3. Create/Update Render Tree:所有CSS文件下載完成,CSSOM構建結束後,和DOM一起生成Render Tree。
  4. Layout:有了Render Tree,瀏覽器已經能知道網頁中有哪些節點、各個節點的CSS定義以及他們的從屬關係。下一步操作稱之為Layout,顧名思義就是計算出每個節點在屏幕中的位置。
  5. Painting:Layout後,瀏覽器已經知道了哪些節點要顯示(which nodes are visible)、每個節點的CSS屬性是什麼(their computed styles)、每個節點在屏幕中的位置是哪裡(geometry)。就進入了最後一步:Painting,按照算出來的規則,通過顯卡,把內容畫到屏幕上。
以上五個步驟前3個步驟之所有使用“Create/Update” 是因為DOM、CSSOM、Render Tree都可能在第一次Painting後又被更新多次,比如JS修改了DOM或者CSS屬性。

Layout和Painting也會被重複執行,除了DOM、CSSOM更新的原因外,圖片下載完成後也需要調用Layout和Painting來更新網頁。


  • 首屏時間和DomContentLoad事件沒有必然的先後關係
  • 所有CSS儘早加載是減少首屏時間的最關鍵
  • js的下載和執行會阻塞Dom樹的構建(嚴謹地說是中斷了Dom樹的更新),所以script標籤放在首屏範圍內的HTML代碼段裡會截斷首屏的內容。
  • script標籤放在body底部,做與不做async或者defer處理,都不會影響首屏時間,但影響DomContentLoad和load的時間,進而影響依賴他們的代碼的執行的開始時間。

回到前面的問題:
script標籤的位置會影響首屏時間麼?
答案是:不影響(如果這里里的首屏指的是頁面從白板變成網頁畫面——也就是第一次Painting),但有可能截斷首屏的內容,使其只顯示上面一部分。

為什麼說是“有可能”呢?,如果該js下載地比css還快,或者script標籤不在第一屏的html裡,實際上是不影響的。明白這一影響邊界非常重要,這樣我們在考察頁面性能瓶頸的時候就有的放矢了。舉個例子:在網頁的第二屏有一個通用模塊,實際上我們是可以把它的js邏輯獨立成一個文件,將模塊的html和js標籤放在一起做成獨立的模板引進來的(如果它的js比較小或者說因為多了一個文件會多佔用一個TCP連接和帶寬,這實際上是另外​​一個話題了,請參考我文章開頭的聲明)。


我們來總結一下:
  • 如果script標籤的位置不在首屏範圍內,不影響首屏時間
  • 所有的script標籤應該放在body底部是很有道理的
  • 但從性能最優的角度考慮,即使在body底部的script標籤也會拖慢首屏出來的速度,因為瀏覽器在最一開始就會請求它對應的js文件,而這,佔用了有限的TCP鏈接數、帶寬甚至運行它所需要的CPU。這也是為什麼script標籤會有async或defer屬性的原因之一。

2016年5月2日 星期一

Nested transactions



User.transaction do
  User.create(username: 'Kotori')
  User.transaction do
    User.create(username: 'Nemu')
    raise ActiveRecord::Rollback
  end
end
both Koori, Nemu created

As mentioned previously ActiveRecord::Rollback does not propagate outside of the containing transaction block and so the parent transaction does not receive the exception nested inside the child. Since the contents of the child transaction are lumped into the parent transaction both records are created! I find it easier to think of nested transactions like the child who dumps its contents into the parent container, leaving the child transaction empty.

User.transaction do
  User.create(username: 'Kotori')
  User.transaction(requires_new: truedo
    User.create(username: 'Nemu')
    raise ActiveRecord::Rollback
  end
end

only “Kotori” is created 

2016年5月1日 星期日

load, autoload, require, require_relative




load, autoload, require, require_relative

load:
load 命令提供了一種最原始的方法,即每次都會重新加載整個文件,刷新內存中的類定義.

autoload:
load 命令每次都加載類有些浪費,很多類並不是一開始就需要,可以用autoload 來先創建一個鉤子,等到真的訪問到的時候再加載:
autoload :Calendar, './calendar.rb'


但這種方式有個問題: 相同常量如果多次定義autoload 鉤子,只有最後一個會被觸發. 設想在實際開發中,類定義可能分佈在多個文件中,所以這種方式並不常用.

require:
和autoload 一樣, require 想解決的也是性能問題: require 只在第一次被調用的時候被觸發,之後針對相同文件的require 就不會真正執行了

require_relative:
require_relative 相當於是默認將當前路徑加入了$LOAD_PATH,不用給相對路徑或絕對路徑, 其他和require 是一致的

2016年4月30日 星期六

Thread-Safety


Rack::Lock => make sure thread safe
def threadsafe!
  @preload_frameworks = true
  @cache_classes      = true
  @dependency_loading = false
  @allow_concurrency  = true
  self
end
sometimes on production rails will remove Rack::Lock => because Web server will handle it => unicorn, Fusion Passenger => single thread

puma => multi thread 

Rails Middleware Walkthrough


ActionDispatch::Static => provide static file on public
Rack::Lock => lock the app down to a single thread
ActiveSupport::Cache::Strategy::LocalCache::Middleware => cache method based on ActiveSupport::Cache::FileStore
easy to use by Rails.cache.read or Rails.cache.write
Rack::Runtime => sets an X-Runtime response header to show spending time
Rack::MethodOverride => if set params[:_method], could reset http method, ex put, delete on form
ActionDispatch::RequestId => set unique request id
Rails::Rack::Logger => log when request start, and request end
ActionDispatch::ShowExceptions & ActionDispatch::DebugExceptions => rescue error, and custom format
ActionDispatch::RemoteIp => detect ip attack
ActionDispatch::Reloader => reload classes in development mode
ActionDispatch::Callbacks =>  We can call before or after methods on this and pass in a block which will then be triggered on each request.
ActiveRecord::ConnectionAdapters::ConnectionManagement => clear db connections
ActiveRecord::QueryCache => active record query cache
ActionDispatch::Cookies, Session::CookieStore and Flash =>  set cookie, sessions
ActionDispatch::ParamsParser => prepare params
ActionDispatch::Head => transfer head request to get
Rack::ConditionalGet and Rack::ETag => set ETag header based on the response body, conditional => if not changed, not process => only send 304

ActionDispatch::BestStandardsSupport => add recommend browser to client 

LOG TAGGING IN RAILS

My::Application.config.log_tags = [ :uuid ]

Now you can filter the log content by a particular request ID to see all output related to a single request 

Clickjacking



Kidnap your click, to create unexpected behavior:
ex: use invisible iframe to controller your click


user X-FRAME-OPTIONS to prevent it 

2016年4月19日 星期二

How key-based cache expiration works




  1. The cache key is fluid part and the cache content is the fixed part
  2. key is calculated from the content
  3. when key changes, simply write the new content to new key
  4. will generate a lot of cache garbage => don’t care => Memcached will automatically evict the oldest keys first when it runs out of space
  5. You deal with dependency structure by tying the model object together on updates
  6. The caching itself then happens in the views based on partials rendering the objects in question

2016年4月17日 星期日

ActiveRecord::Observer


callback, but not very related to model
we can use observer

class AuditObserver < ActiveRecord::Observer
  observe :account:balance

  def after_update(record)
    AuditTrail.new(record"UPDATED")
  end
end


Storing Observers in Rails

If you’re using Active Record within Rails, observer classes are usually stored in app/models with the naming convention of app/models/audit_observer.rb.

Configuration

In order to activate an observer, list it in the config.active_record.observers configuration setting in yourconfig/application.rb file.
config.active_record.observers = :comment_observer, :signup_observer

Observers will not be invoked unless you define these in your application configuration. 

2016年4月16日 星期六

how to build a virtual dom tree

如何實現一個Virtual DOM算法

  1. use javascript object to present the structure of dom, and use it to build a real dom tree, then insert to document
  2. when state updated, recreate a object tree, and then compare old tree and new tree, and record the diff
  3. use 2.) diff to 1.) real dom tree

2.1. how to compare:
1.Depth-first search for new and old tree, and add unique mark
2.diff type: REPLACE, REORDER, PROPS, TEXT

3.compare list: ex => abcdefghi =>abchdfgij 

2016年4月10日 星期日

css 原理

 http://kb.cnblogs.com/page/125663/


from right to left effect:
DIV#divBox p span.red{color:red;} => find class ‘red’, then find span, then find p ….
in order to filter some unrelated 元素 quickly

how to optimize css

  1. 不要在ID选择器前使用标签名
    一般写法:DIV#divBox

      更好写法:#divBox
      解释:因为ID选择器是唯一的,加上div反而增加不必要的 CSS 匹配。
  2. 不要在 class 选择器前使用标签名
    一般写法:span.red
    更好写法:.red
    解释:同第一条,但如果你定义了多个.red,而且在不同的元素下是样式不一样,则不能去掉,比如你css文件中定义如下:

      p.red{color:red;}
      span.red{color:#ff00ff}
    
    
      如果是这样定义的就不要去掉,去掉后就会混淆,不过建议最好不要这样写
  3. 尽量少使用层级关系
    一般写法:#divBoxp.red{color:red;}
    更好写法:.red{..}
  4. 使用 class 代替层级关系
    一般写法:#divBox ul li a{display:block;}
    更好写法:.block{display:block;}
  5. 在 CSS 渲染效率中 id 和 class 的效率是基本相当的
    class 会在第一次载入中被缓存,在层叠中会有更加好的效果,在根部元素采用id会具有更加好(id有微妙的速度优势)。

how browser work








ruby object


  • ruby中,一切皆對象
  • 理解ruby對像模型
  • 了解ruby查找方法的方式

描述了Ruby中方法調用的過程,“向左一步進入該對象的類,然後沿著祖先鏈一直查找方法,找到方法之後,根據自身的綁定執行該方法”。 因此,對象本身只有一組綁定,而方法定義都是在類中。那麼上面說到的單件方法和類宏應該在什麼地方定義呢?單件方法肯定不能定義在類中,否則將會影響該類的所有實例對象。類本身也是對象,類的方法不能定義在自身,因為對象的方法必須定義在對象的類中,而類對象的類是Class,如果把類方法定義到Class上,那麼所有的類對像都會擁有該方法。這一切迷思的答案都來源於一個Ruby中的高級概念,Eigenclass Eigenclass在Ruby中,當調用obj.class向一個對象索要它的類的時候,編譯器並沒有告訴大家全部的真相,你得到的類並不是你看到的類,你得到的是一個對象特有的隱藏類,這就是該對象的Eigenclass,雖然Object#class方法想把關於Eigenclass的信息隱藏起來,但是,存在即存在,總會被人挖出來的。 



Eigenclass是一個類,但是是一個很特殊的類,它只能有一個實例,且不能被繼承,但是其自身可以繼承其它類。因此,所有的對像都有一個自己的Eigenclass,單件方法就定義在該對象的Eigenclass中,類宏定義在該類對象的Eigenclass中

為了區分普通類和Eigenclass,Ruby會使用“#"表明該類是一個Eigenclass。 
*一個實例對象的Eigenclass的父類是該對象的類 
*一個類對象的Eigenclass的父類是該類對象的父類的EigenClass。