2012年2月23日

SocketManager的設計問題

現在的設計是:
QuoteProxy取得SocketManager,然後QuoteProxy要用SocketManager發送與取得資料。

SocketManager在資料出來這一端,有一些可能的途徑:
1. SocketManager單純就只是一個EventDispatcher,取得來自server的raw text後event dispatch出去。QuoteProxy (還有未來的AlertProxy,OrderReplyProxy等等)parse、update proxy,然後由 QuoteProxy 丟出 message。好處是SocketManager就可以放在基本功能類別讓大家Reference,這樣就不需要ISocketManager了。

2. SocketManager 要負責 Parse,根據 Parse 的結果,dispatch event 到正確的 proxy。但這樣SocketManager就必須要知道所有可能透過socket發生的channel,而且因為會被多個namespace reference到,所以需要ISocketManager

SocketManager在被驅動這一端,有一些可能的路徑:
1. 每個Proxy自己知道怎麼產生「socket訂閱字串」,直接呼叫SocketManager的send
2. Proxy產生Query,丟到SocketManager。SocketManager要知道怎麼處理每個query。

1配1,2配2。現在的想法是用2,結構上比較decoupled,但現在就要寫很多碼。

2011年9月1日

一份重要簡報的導覽

老實說,自從一個規模頗大的官網從手中溜走之後,我很久沒有關心 css 相關的議題了。以前累積下來的CSS知識,這兩三年也讓我輕鬆砍了不少規模中等的網站。但這次,為了處理一個規模相當大的官網切版工作,再加上non-table layout + IE 6 compatible 的要求,我又回來跟CSS裝熟了。

但比較大的問題是:1)設計不是我這邊出的,只能被動收件,而且切第一個版的時候,後面的設計還有一半以上沒出來,2)我以前從來不在乎non-table,最大的擋箭牌就是IE 6。但當客戶舉了業界第一品牌的網站給我看後(馬的,他們的設計比我們簡單一百倍好嗎?)硬著頭皮,只好再度表演特技了。

這三年關於refactor的心得,讓我深信:「do it right once and refactor forever」是千年不變的真理(好拉,其實我也不相信這鬼話),但當我重複在類似的html架構下,寫下近乎完全相同的「border : 1px solid…」時,我就知道事情大條了:CSS中,code duplication的情況太嚴重了,而且,我的refactor沒有unit test做保證。好,那就只能第一次就搞定,不能再想refactor了。因此,我光首頁就重做了三次,第一個內頁就重做了兩次。兩頁花了我一整個星期(一整個星期?C#和AS早就不知道寫到哪了!),還因此每天被人照三餐問候進度….唉…

問題的根源在哪?高中時,跟王浩洋玩prolog的時候,就得到的經驗是: pattern matching rule set 的finite state system,都有難以人工debug的問題,也就無法開發系統(當然,prolog是認為:這個debug的事情,可以由prolog寫成的自動debug系統來做,請各位大笑三聲)。以前我就隱隱覺得CSS selector是個爛東西,但以為是selector跟FP(Functional Programming)比較像的原因;但這次的經驗,讓我確認selector是個更糟糕的東西:他就是pattern matching rule set,而且rule的priority還爛得可怕(specificity和什麼鬼!important)。但,當然也有另一個可能,就是阿拉丁是個爛咖,連html+CSS也寫不好!

前幾天,從http://minipai.tw/post/64看到了http://www.slideshare.net/stubbornella/our-best-practices-are-killing-us這份簡報,讓我確定:我不是爛咖,因為每個人都有這樣的困擾。因為有人說看不懂這份簡報,所以,我決定對這份簡報做個小小的導覽:

--------這是分隔線,以下請配合簡報服用---

簡報一開始到21頁,檢查了許多知名網站的CSS,如facebook等。用數字告訴我們,CSS 的duplication在這些網站中,不停的發生。也就是,這並不是誰的問題,而是我們所有人的問題。

接下來,他用幾頁說明他的觀點:CSS(就像 Javascript一樣)並不糟,問題在於我們用錯工具(好吧,看到第五遍,我承認我有被說服到,但支撐front-end的兩大支柱都被人說爛?恩…)

然後,作者列舉了三個值得討論的best practice,並認為這三個迷思讓大家產生今天的問題:Don’t add any extra elements (不增加額外的tag),Don’t add classes (不要用class),Use descendent selectors exclusively (僅靠單純的tag疊加選擇子達成)。但這三個best practice,導致了specificity快速增加的問題。Specificity是CSS計算rule使用優先順序的規則,meyer 的書解釋得很清楚,又有中文版,大家可以去看一下。

接下來就是一串舉例,告訴我們各種情況下,specificity怎麼快速增加。那個 sidebar的例子,相信做過大官網切版的人,都會感同身受。最後,這樣寫css的方式,會讓我們只能靠firebug或其他類似工具才能確認我們的css code是否正確。

而且,更可怕的,specificity會因為官網上線後增加功能而繼續往上疊加。有些人認為!important會解決這樣的問題,但不!!important會帶來更多的問題。92頁告訴你這個極致會是怎麼樣糟糕的狀況。

之前都是處理selector,94頁開始看style的內容。這邊舉了一個例子稍微值得解釋一下。前面的#sidebar h3憑空出現,讓整個style都做了新的設定。但#sidebar .collaborators h3的內容,其實跟最原始的h3相同。但在css中,我們只能把h3的定義整個拉到#sidebar .collaborators h3再放一次,因為在css中,我們沒有辦法「中和」#sidebar h3產生的影響。這是為什麼簡報一開始,在這些大網站上,你會看到這麼多重複宣告的原因。

怎麼解決?98頁提了幾個思考點:Add non-semantic elements judiciously (慎重考慮加上非語意的tag,比如div), Keep specificity as low as possible(保持specificity盡量低),Abstract repeating visual patterns (把重複的視覺架構萃取出來),Use specificity to define your architecture (定html架構的時候,要把specificity考慮進去)。

後面舉了facebook的media block為例,說明設計時的條件,和對應的作法。(Facebook我沒那麼熟,不過過一陣子會有案子發生,到時來檢查這個例子)。

109頁,舉了兩個最近不停在我眼前出現的字眼:Sass和Less。簡單講,由於CSS的破爛設計,css duplication是會大量發生的。但如果我們有另外一個語言,本身是dry的,可以產生我們要的破爛CSS。那讓程式去產生破爛CSS,我們人只要維護這個語言寫成的碼就可以了;Sass和Less就是這樣的語言。看起來,Sass已經是大部分web developer的首選了。最近試用了一下Sass,暫時無法評論,得等下次有大案子再說了。

-------------這是分隔線,導覽到此結束,以下是碎碎念

希望這樣的導覽對大家有幫助。最後要協同報告的是:Javascript也很爛,而且也是爛到爆;所以同樣的工作也有人做在javascript身上,就是大家最近常聽到的coffeescript。這一次的CSS探險,讓我確定了一個很重要的事情:不管HTML 5再棒,有Javascript和CSS護身,還有死不知恥的W3C consortium不清楚現實開發狀況,Flash 安啦!

還有一點補充,grid system 960的作者,在http://www.slideshare.net/nathansmith/refresh-okc這份簡報的第50, 51頁,也回應了nicole的觀點。請大家自行參照...

還有,我這次很幸運的完全不知道這三個迷思。所以,我對於該加的div絕不手軟,該用的class絕不少用。雖然還是很多的code duplication,但是最近做了一兩個重要的refactor,都很順利。不過,根本解決之道,應該還是使用Sass或Less這樣的工具。但對於一般的designer來說該怎麼辦?我還真不知道。

2011年6月22日

關於設計給製作的.psd 檔案該有的規矩(用在.ai也通)

這是常見的困擾,所以我相信已經有別人寫過了。最近經手的案子,設計都不是我找的,困擾發生兩次,就該找解決方案。

也不知道會有多少設計真的願意照做,但至少對製作單位來說,用這樣的原則先整理檔案,應該也會方便後續的製作。

------這一條叫做分隔線------

Photoshop的檔案分層說明:
  1. 除了大背景之外,請根據功能,將圖層群組起來。
  2. 群組之後,請給予一個能夠描述該群組用途的名稱。最常見的是使用群組的設計目的(選單、標頭、標籤列、banner列等等)來命名。
  3. 若有相同的設計目的,但卻處於頁面的不同位置,請分開成不同的群組,並在功能性之外,加上位置的描述(上選單、左選單)之類的,
  4. 群組中,請根據圖層的功能姓再繼續命名。如果有是使用多個圖層才能完成的視覺效果,請把相關的圖層再群組起來。
  5. 圖層,也盡量取有描述性的名稱(如「按鈕陰影」、「上部光影」等)。尤其是使用單獨一層很難看見的效果(如Difference、Overlay、Lighten)時,正確的目的描述,可以讓製作單位減少錯殺圖層的可能性。
  6. 內容頁的psd檔:如果好幾頁共用相同的設計元素,請把每一個頁面的特殊部分做成一個top-level 群組。幾個頁面共用的元素(如選單),則獨立在外成一個群組,並在群組名稱後面增加「(共用)」這樣的字眼
  7. 文字的部分,請勿轉成bitmap。因為對製作單位來說,文字的大小和間距這些資訊更為重要。雖然psd文件從Mac到PC(或反過來)上,字體與位置有可能會跑掉,但有文字的大小和間距資訊,製作單位比較容易再處理。
檔案交付前,請設計單位先做以下的檢查:
  1. 檔案打開來,除了大背景之外,所有其他的圖層都應該在某個群組中。
  2. 請確認所有的圖層,都使用了目的性或功能姓的描述名稱,而不是Photoshop預設的「Layer 5」或「Layer 3 copy 11」之類的。
  3. 請確認圖層群組與子群組的名稱,都使用了正確的目的性或功能性描述。
  4. 請把圖層群組開開關關,確認每個圖層群組都「僅包含」群組名稱所指的內容。在我們的經驗中,這點讓我們製作人員去檢查,出錯的機率是百分之百,且會大幅增加製作上來來回回的時間。
  5. 如果需要,請不吝另外給文件,說明您的分層。


2011年5月9日

在.aspx中直接呼叫System.Diagnostics.Trace.WriteLine不會有作用

這個問題之前遇到過,被以前的外包解決過。這次自己遇到,卻一直沒想起來有這件事情,所以把原來的連結貼一遍:

http://www.alexthissen.nl/blogs/main/archive/2007/02/11/viewing-diagnostics-trace-info-in-an-asp-net-website.aspx

簡單講:asp.net會把我們的.aspx轉換成.cs(或.vb)。然後再呼叫csc把產生的程式碼編譯完成。後面這道編譯的手續,如果沒有把/d:Trace打開,產生的程式碼就會忽略System.Diagnostics.Trace。這篇教的就是怎麼把這個選項打開。

2011年5月6日

「Viewstate MAC 的驗證失敗」 的另一個可能

「Viewstate MAC 的驗證失敗。blah blah blah machineKey 設定 blah blah」錯誤,是一個常見的 asp.net webform 問題(好累,以後都要說是 MVC 還是 webform )。起因多半來自兩個:

1. 是 webfarm 的設定,就是向A主機要了xxx.aspx,但postback卻到了B主機。實務上,我們還是寧可用big IP這類的產品做分流,遠比用軟體手段設定session state mirror問題要少。這個部分多半要找網管確認問題,比較麻煩。

2. 是讓頁面自動做postback,但卻在Viewstate還沒load完前就進行。

以上的內容,這裡有比較詳細的解釋

昨天客戶的客戶又發生這樣的錯誤,原來以為是 1.,但客戶說他自己之前偶而也會遇到。這個「偶而」讓我覺得很奇怪,因為公司內部是不會透過Big IP的。把 asp.net 2.0 關於 machinekey 的 security 章節讀完了以後,才想到:阿,Autogenerate 的 machineKey也會是問題阿!

Google了一下,果然:
http://social.msdn.microsoft.com/Forums/en-US/netfxsetup/thread/1a3a947b-fda0-4446-a4c7-7e8730d4064d/

上面討論串的回答有提到這一點,也就是每次app pool 被recycle以後,machineKey就會重新產生一次。如果使用者之前就進入我們的網站,但卻很久沒有進行任何操作,等到 app pool 被 recycle了以後,使用者卻用recycle之前的網頁進行postback,就會導致這樣的情況發生。

所以比較安全的作法,就還是把machineKey給定下來。

2011年5月3日

JQuery Timer

老實說,我並不是很常寫複雜的javascript。最近手癢把一個原來要用flash完成的自動換圖,改用javascript寫。由於對 setInterval 深惡痛覺,就找了半天看有沒有Timer可用。找了半天,發現大部分的都用callback,也有closure的問題,再找下去也不是辦法,就決定自己寫一個。

function Timer(delay, repeatCount) {
this.delay = delay;
this.repeatCount = repeatCount;
this.currentCount = 0;
this.timeHandle = 0;
this.running = false;
this.start = function() {
this.timeHandle = setInterval(Timer.delegate(this, this._timer), this.delay);
running = true;
}
this.reset = function() {
this.stop();
this.currentCount = 0;
}
this.stop = function() {
if (this.timeHandle != 0) {
clearInterval(this.timeHandle);
this.timeHandle = 0;
}
this.running = false;
}
this._timer = function() {
$(this).trigger($.Event("timer"));
if (this.repeatCount > 0) {
this.currentCount++;
if (this.currentCount >= this.repeatCount) {
this.reset();
}
}
}
}
Timer.delegate = function(obj, func) {
var f = function() {
var target = arguments.callee.target;
var func = arguments.callee.func;
return func.apply(target, arguments);
};
f.target = obj;
f.func = func;
return f;
}

使用的方式:需要先載入jquery(只是要一個能 trigger event 的 framework)。用 bind("timer", handler) 去接收timer事件。

var ct = 0;
function timer_tick(event) {
ct++;
alert(ct + "," + this.currentCount);
}

var timer = new Timer(5000, 3);
$(timer).bind("timer", timer_tick);
timer.start();

這個是照著flash.utils.Timer刻的,用法也幾乎相同(用javascript模仿read-only,實在太囉唆了,所以沒做),不熟悉的人可以去 http://help.adobe.com/zh_TW/AS3LCR/Flash_10.0/flash/utils/Timer.html 看。至於這麼一點功能卻要 load 一個龐大的 jquery,是不是值得,就請大家自己判斷了。

2009年6月29日

FDB選擇browser的問題

最近恢復使用fdb來debug swf檔案。但在我的機器上遇到一個麻煩的問題,就是每次都用safari打開debug player,偏偏safari在我的機器上跑得並不順。經過了一些搜尋,找到這一篇:

http://www.jetbrains.net/jira/browse/IDEADEV-34701

處理了一下,很快就能用firefox。但是遇到了一些不明的問題,幾乎不能設定breakpoint。ie就沒有這個問題,我想,單純只是因為ActiveX的架構...