CSS

[.Note] 10 Things I Learned from JQuery Source (or more then 10?)


10 Things I Learned From The JQuery Source
From Paul Irish

一篇很棒的演講,由專家帶領我們從JQuery的原始碼中學習一些JQuery所用的JavaScript Pattern以及設計方式.

自從在OSDC2010上聽了Gugod的Less is More,JQuery這個框架的簡潔性以及設計的原則就一直吸引著我.
這個演講剛好讓我以後在用JQuery的時候能更輕易的去看source.

以下是筆記:

1.JQuery的Convention之一: Closure Pattern:
(function(){ ... })();

!function(){ ... }()

後面的括號代表這是self executing function: run itself immediately

favorite pattern:
(function(window,document,undefined){
    ....
})(this,document)

把window,document當成變數傳入closure,這樣的好處是:
1.如果有其他全域變數例如 undefined = true; // break all undifined comparison
而closure避免了這些干擾
2.minification:
最佳化後會變成: function(A,B,C){}(this,document), 可以省下一些字元

2. async recursion

Self repeating: 會不斷的執行,不論前一項有沒有執行完,
例如
setInterval(function(){ 
   doStuff();
},100) // is very evil

而self executing function能確保執行到尾巴之後才會執行第二遍
(function loops(){
    doStuff();
    $('#update').load('awesomething.php',function(){
        loops();
    })
    setTimeout(loops,100);
})()

3.如何找到函式: 找 function name + : , ex: "noConflict:"

4.Jquery.noConflict:
在開始時將 原本的 $ 儲存為 _$, 並在呼叫noConflict時復原.

5.jQuery.props
小型的參數字典,自動將Html與Dom Api上一些相同意思但名稱不同的參數作對應
讓開發者不需要記得所有的東西.
也可以用在.attr:
ex: WAI ARIA
$(elem).attr('aria-disabledby','asdasdasd');

$.props['adb'] = 'aria-disabledby';
=>
$(elem).attr('adb') = 'asdasdasd';

6. fadeIn() : defined your own speeds:
JQuery內部的 speed 定義了各種速度:
speeds: {slow:800 ,fast:200 ,_default:800}
可以由外部加入自訂的速度
jQuery.fx.speeds.fastopen= ($.browser.msie && $.browser.version < 8 ) ? 800 : 400;
//在IE7以下速度為800,其他瀏覽器為400

$('#stuff').fadeIn('fastopen');
7.JQuery.ready(...) 會檢查DOM準備好沒,在準備完畢時執行function,

bindReady(); // IEContentLoad: solve by great Italian hacker,

using doScroll check to check if DOM ready in IE :

doScroll(left); //will raise exception if DOM not ready.

8.getJSON : shorthand methods:

jQuery ajax() holds anything, but get,post,getJSON,getScript shorten the varible.

9.selector performence.
$('#id') vs $('#id tag.thing')
$('#id tag.thing') will self parse to => $('#id').find('tag.thing');
$('#id').find('tag.thing')
$(':password') === $('*:password') 
so better provide tagname ex: $('input:password');

10.getJSON: function protect 會用regex檢查資料是否為JSON,如果是的話就pass,
不是的話會呼叫 (new Function("return" + data))();
這叫Function constructor: 回傳
function(){return data;}
=== eval('('+data')');
但是避開使用邪惡的eval 

11 $.unique(err) : duck punch
$.unique能夠過濾相同的DOM元素,讓陣列只有unique的元素
但不對應基本物件 使用duck punch來擴充unique方法:
(function($){

    _old = $.unique()

    if(!!arr[0].nodeType){
        return _old.apply(this,arguments);
    } else {
        return $.grep(arr,function(v,k){
            return $.inArray(v,arr) === k
        });
    }
})(jQuery);

12.quene: $(elem).fadeIn().delay(1000).fadeOut(); 可以使用quene方法改寫成
$(elem).quene(function(){
        $(elem).delay(1000).fadeOut();
});

13.$.support
support使用一個HTML div,內部包含table,/a等等各項元素,
support會檢查瀏覽器能不能辨識其中的元素,來做瀏覽器的相容性檢查

14.bit.ly/jqsource : 一起來看JQuery Source

[Extension Method] 什麼是擴張方法??

ExtensionMethod

什麼是Extension Method?


Extension Method可以將方法給"加"在現有的Class上:

舉例來說:
String.IsNullOrEmpty("Hello Ext");
有時候我會覺得這樣看起來有點不直覺...這時候就可以使用Extension Method來改寫,
將IsNullOrEmpty給"加"在string物件之上:
public static class StringExtensions{
    public static bool IsNullOrEmpty(this string content){
        return String.IsNullOrEmpty(content);
    }
}
string hello = "Hello Ext"
hello.IsNullOrEmpty();

...好吧,我承認這個例子有點無聊
不過Extension Method就像這樣,可以宣告靜態方法,並於compile時將這些方法附加於物件
而不需要修改物件的原始碼或是使用繼承關係
就像是動態語言的"Duck Typing",可以將行為附加在已經有的class上面.

How to use?

C#:
1.將Extension Method宣告為靜態class以及靜態方法
2.第一個參數為this + 要附加的物件: IsNullOrEmpty(this string content)

VB
1.import System.Runtime.CompilerService
2.宣告Module,宣告靜態方法(shared),第一個參數為要附加的物件:
3.於方法前加入extension標籤: <Extension()>

Notice:

1.當extension Method與物件本身的方法衝突時,永遠是本體優先
2.可繼承,影響到所有繼承的物件

那麼...為什麼要用Extension呢?

我的看法是,它可以很直覺化的將行為給附加在沒有原始碼,或是系統提供的物件上
舉一個專案上碰到的例子來說:
Response.setHeader( "Pragma", "no-cache" );
Response.addHeader( "Cache-Control", "no-cache" );
Response.setDateHeader("Expires", 0);
是一段寫入取消快取的code,用extract function可以變成:
NoCache(Response);
但如果還有別的頁面要使用NoCache這個方法,NoCache要移到哪裡呢?
要獨立為靜態方法,還是抽出到base class呢?
Extension Method提供了一個最直覺的寫法:
Response.NoCache();

物件的操作與物件本身合為一體,只有Beautiful這個字可以形容了.

when not to?


在extension之外可以直接修改程式時,應該refactor away from extension method
在時常變更,或有繼承,多型關係的class最好不要使用,也無法附加到Static Class上
另外,如果實作於介面上:
1.會影響到每個實作介面的class
2.如果實作複數介面有可能會衝突

Extention Method Library


.NET本身就有一些物件是以Extension Method來提供擴充功能的,例如說一些LINQ方法,datatable的LINQ對應等等

Extention Method Library提供更多物件的擴充功能

像是int可以使用ruby like的 .times語法
4.times( (n) => Console.Writeln(n +" Times"); );

還有Session可以使用.Get<T>來指定型別
.Ensure<T>來確保不會拿到null值等等方便的擴張功能.

[3 way to estimate]估算專案時間的三種方法

gantt

為什麼軟體開發的時間難以估計?為什麼專案往往無法在預定時間內完成?


1.軟體開發的時間本來就難以估計

軟體開發本來就是個複雜的流程,除了許多複雜的邏輯與問題處理以外,
這個產業發展的速度太快,新的技術不斷的推出
使得每個專案都會遇到沒使用過的技術,沒有解決過的問題,即使是經驗豐富的開發者,
也不一定能準確的估算解決一個新的問題或技術要花多少時間.

2.軟體開發的需求,以及範圍經常變更

有許多的需求是隨著系統開發,使用者對於系統有更明確想法而產生的.
而在需求修改後,新的完成時間往往難以估算.
另外,專案開發一定必須debug,而debug的時間幾乎是完全無法預估,
許多的專案估算時間時沒有把debug與整合的時間算到專案開發時間內,
造成debug吃掉了本來應該用來開發的時間.

3.軟體開發有"技術債務",如果不維持品質,為了滿足短期交付而交出缺乏品質的程式碼,會導致後面的開發困難.
缺乏品質的程式碼的例子有:充滿大量剪貼的程式碼,許多用不到或浮誇的邏輯,
程式碼風格缺乏一致性,程式架構緊密偶合,肥大的class或頁面,沒有測試等等.
短期內這些問題並不會造成什麼嚴重的後果,但是就如"技術債務"這個詞所說的,
當這些問題沒有在發生的時候馬上處理,之後就要花上好幾倍的時間去處理這些債務.

估算專案時間的三種方法:


1:Time Base:

或稱為"Deadline Base",以專案的交付時間往回倒推.
例如說有三個月的開發時間,那麼就有2個禮拜作需求分析,2個禮拜做系統設計,5個禮拜開發,3個禮拜測試.
仔細一想就能明白,這個估算與實際上的開發內容完全無關,只是大致上的估算而已.
這種方式由來已久,並廣泛的用在各種行業與我們的生活,例如說考試前兩個禮拜要開始唸書
出國前3天要準備好護照與機票等等.
不過由於軟體開發的複雜性,這種方式並不能夠準確的估計專案的完成時間

2.Experience Base:

"經驗導向"為Time Base的延伸,基本上是去詢問工程師這個功能要做多久,
加上自己的經驗而判斷出來大概的時間,這種方式的準確度比較高,但是;
由於軟體開發的多變性與需求的變化,這並不一定能準確的估算,
而且人都有過短估計的傾向,與之相反的,
有時候這會變成"Promise Base",意思是要工程師在自己估算的時間準時交貨
但第一,估算一定與實際上要完成的時間與工作量有差距,這種估算方式就會導致
1.工程師儘量延長估算時間,避免無法完成
2.加班來達成自己的預估
3.延長完成時間以達成預估
比較好的作法是提供有彈性的預估範圍 -- 一個樂觀預估,一個一般預估.

3.Fact Base:

就是Agile裡的Burndown Chart,將系統切分為可重覆,類似的流程,
然後以過去開發的平均時間,來估算未來的完成時間,這種方法比較接近統計學
而且:
1.可以反映出開發者的速率,經驗較淺的人會花比較多時間完成同樣的項目,而這會反映在對整個專案速率的推估上
2.可以限制專案開發的範圍,因為完成時間是以功能/功能完成時間而推估,所以減少功能=提早完成時間,這個等式變得很明顯,也可以強迫負責人找出真正重要的功能去完成.