2003
01 02 03 04 05 06 07 08 09 10 11 12
2006
01 02 03 04 05 06 07 08 09 10 11 12
2007
01 02 03 04 05 06 07 08 09 10 11 12
2008
01 02 03 04 05 06 07 08 09 10 11 12
2009
01 02 03 04 05 06 07 08 09 10 11 12
2010
01 02 03 04 05 06 07 08 09 10 11 12
2011
01 02 03 04 05 06 07 08 09 10 11 12
2017
01 02 03 04 05 06 07 08 09 10 11 12
2018
01 02 03 04 05 06 07 08 09 10 11 12
 
Jun
12
2007

以 delegation model 為基礎的伺服器操作抽象化設計

非常饒舌的標題。 Nick Chubb Jerseys 其實白話是,如何用 Objective-C 設計一個類似 ObjectiveFlickr 的 framework 來包裝一些 web service 操作。 Fjallraven Kanken Classic 最近在重寫一些舊的噁心程式碼,也順便看了一下 ObjectiveFlickr ,發現其實大家要做的事情都很類似,都是抽象化伺服器操作。 nike air max 95 pas cher 不只目標很像,竟然連程式的寫法也相當類似(其中許多巧合大概得歸咎於 Cocoa 在這方面的缺陷),例如大家都重新用 CFReadStream 之類的 API 重新包裝了一個 HTTPConnection 物件而不用 NSURLConnection 等。 其中我遇到一個比較值得討論的共同問題是這樣的:由於網路程式的特性,synchronous call 顯得不太合適,於是「射後不理、出事了再回頭找人」的 asynchronous behavior 便成為網路程式設計的典範。 Nike Air Max Uptempo Cocoa 在實作 asynchronous behavior 採用的是 delegation model,也就是指定一個委託人,等到網路那端有消息了再去呼叫委託人的某些 method,在我看來其實只是一種 callback function 的物件化版本。 sac fjällräven kånken 然而以 ObjectiveFlickr 的設計來看,使用 delegation 可能會出一些問題: [invoc setDelegate: A]; [invoc callMethod: @"flickr.get.xxx" ...]; [invoc setDelegate: B]; [invoc callMethod: @"flickr.put.xxx" ...]; 假設第二行的 callMethod 的網路回應還沒回來之前就已經執行完第三行,等到第二行的網路回應回來了,卻發現竟然「所託非人」,本來的委託人 A 被換成 B ,就有可能出問題了。 究竟為何導致這樣的問題呢?我發現大家蠻常採用一種做法有可能是原因:用來代表 Server 的物件模型通常都會用各種手段取得一個單一的 HTTPConnection 物件 reference,例如 Server 本身擁有一個 HTTPConnection member。其他人的理由我不知道,我本身會這樣做的原因是記憶體管理!HTTPConnection 本身不能是一個 autoreleased 的物件,因為它必須要夠「長壽」到網路回應來,將後事交代給委託人以後才能安息。所以我們的 Server 需要 init 一個 HTTPConnection。 nike tn requin 然而等到它交代完後事了以後,根據 Cocoa Memory Management 原則,必須由當初 init 它的人,也就是 Server,來親手了結它的性命!萬般無奈下,只好讓 Server 與 HTTPConnection 建立一個其實不必要的從屬關係,讓 Server 能夠在必要時 release HTTPConnection。 Jordan 4 Sale 讓 Server 擁有一個單一的 HTTPConnection 物件為何會導致一開始提到的奇怪問題?仔細思考,問題出在「單一」和「非同步」。因為手上一次只能有一個 HTTPConnection ,在「連線開始」和「連線結束」之間又有可能改變物件的行為,導致一種隱含的相依關係:在一個連線結束之前,會改變內部的動作都不允許,甚至包括另外一個邏輯上不相依的連線(例如同時取得 contact list 和 photo list 邏輯上可以並行,但因為需要不同的委託人來處理所以會改變內部的 delegation)。 Andre Ethier Jersey 這樣的設計有可能讓使用者在 delegate method 上加上額外的邏輯來呼叫下一個連線(已確保此連線結束)或是不斷去 polling 看看連線結束了沒。 adidas y3 pas cher 我認為合理的設計是這樣子的,讓每個 HTTPConnection 都記得屬於自己的委託人,並且 Server 和 HTTPConnection 物件之間根本不需要那麼強的關係。在每次要連線時,直接產生一個新的 HTTPConnection,告知其委託人即可。 問題又來了,每次產生一個新的 HTTPConnection ,屆時 Server 將沒有辦法回收記憶體,發生 memory leak。解法很簡單,直接在 HTTPConnection 自己連線結束的 callback 最後解決自己。但是這樣子仍舊違反了記憶體管理原則啊?Server init 卻沒有 release,不太好吧。 Nike Air Max 2016 Goedkoop 於是,做一點小修正:Server 要產生 HTTPConnection 時,必須產生 autoreleased 的物件,而等到 HTTPConnection 被告知要展開連線的時候,[self retain] 。等到 HTTPConnection 連線結束或是錯誤發生,release itself。(什麼,這麼 trivial ?那上面寫這麼多幹嘛?我剛想到的時候也有這種感覺) 話說回來, Objective-C 2.0 有了 garbage collection 以後以上就全都是屁了,讓我們為 Leopard 歡呼吧! P.S.

 

Annotations RSS

“我想我還是等 Objective-C 2.0 之後再來學 Cocoa 好了 lol”

---ericsk. 4/12, 2007

“後來想想,其實不要堅持 Server model 是 singleton 並且限制每個 Server model 「只能做一次連線」,好像就沒問題了說~ orz”

---yllan. 4/12, 2007

“ObjC2 虽然引入了GC的功能,但是其实说实话,我宁愿没有。就好像现在我尽可能不用@try @catch @finally一样。

事情都是矛盾的,有利必有弊,相信引入GC以后一定会有相当的overhead来做为tradeoff的。

随便说说,kk”

---南木杉. 4/20, 2007
 
 

Write Concisely