Skip to main content

[Flex] 再談 Cairngorm2 framework

最近很不怕死的支援了一個 ERP project(常做半路接手或支援的工作),原始的開發團隊使用的是 Flex 4 SDK, Cairngorm2 框架,雖然上一次發表 Cairngorm2 的文章是兩年前,不過還是很快的進入狀況。

以下是真實開發後使用 Cairngorm2 的個人感想:
先談缺點...(果然迫不及待啊...)
  1. Singleton ModelLocator 的設計果然是一個敗筆:
    不使用 DI(依賴注入)的話,每次新增一個 Model 都是一種折磨,尤其是團隊開發,新增、修改 = 在 ModelLocator 引入或修改。每個 View 都可以操作所有在 ModelLocator 的 public data,Model 內有大量的 bindable IListCollection,因為不這樣做 list 無法同步。若沒有完整列出清單的話,可能有不同 Model 分別持有相同的 list data query。
    更麻煩的是,如果是非同步 update 的 data ,Model 就必須持有兩份相同的 data instance 供比對操作...

  2. Bindable 是個兩面刀:
    有它會讓你上天堂,也很有可能更快讓你下地獄...為了達到資料同步,必須大量的綁定 View 所使用的 deta,Model 無法主動通知做了啥事(除非是建一個公開綁定的屬性跟 Views 綁在一起,又或者透過 CairngormEvent 回 call viewHelper ,但是前提是這個 Event 必須註冊到對應 command 又是一堆 C & E)
    不然就是得使用 BindingUtils 做 watcher,但是重點就是 Model 必須公開綁定所有待操作的資料!總之如果一開始沒有規劃好的話,團隊開發就是一團亂...addCommand() 都 add 不完。

  3. 一點小事情就需要一個 command,與對應的 Event:
    在團隊開發中,如果核心 command 沒有開立完整的話,有時候 view 相關的 command 所操作部份都太過 detail ,會造成差不多的東西可能都要搞好幾份...當然這個情況已經在手上的專案看到了...

  4. Delegate 與 Command 也多多:
    Delegate 明明是用來組織分類對外連線部分,並且做 data parse 又或者配合一個 Command 處理完後送回分類好的 Model,但是一開發起來卻變成每個 view 都有自己一組 delegate+command+model,不然很難分開開發,每次新增修改都要動用到 FrontController, ModelLocator,每天光同步 code 就同步不完。
    不過還是老話一句,事前有規劃好還是可以減少很多多餘的工作。但是太多團隊開發都有時程壓力,想要好好規劃也要看 SA 願不願意花時間設計...

  5. Views 也是亂七八糟:
    Views 可以直接操作 Model public data 已經不是新聞,正因為可以直接操作,所以 Views 有可能會包含大量操作 data 邏輯,下場就是差不多的功能在不同的 View 都有相同的 functions...除非很認真的送回 Model 做更新,這樣有時候也很危險,因為很可能 Views 在一個不小心就改到 Model data 還無所知覺, bug 就是這樣來的!!!!

再來是優點...
呃...列不出來啊~~~~~~~果然 PureMVC 還是我的本命啊~~

不過說實話,有好好的初期規劃,應該還是不會陷入無限的混亂迴圈啦!
Cairngorm + DI 應該是個不錯的選擇...在 Cairngorm3 已經有看到 [Inject] 相關字眼的 metadata 應該是已經大量的被改善過了吧?

結論:
公開的 Singleton design pattern 果然要小心使用啊!
Cairngorm2 已經落伍了,請改用 3 吧...= =

Comments

  1. 不過實際上, Cairngorm 3 只是提供一個方針和一些函式庫而已,並沒有提供MVC框架。

    ReplyDelete
  2. @葉山 輔助函式庫應該有讓 Cairngorm 好用多吧?我是放棄它了,跟它無緣,要不是支援專案也不會想去使用它...= =

    ReplyDelete

Post a Comment

Popular posts from this blog

PureMVC for Unity

幾個月前改用 Unity 開發遊戲,到目前的心得為:組件式開發真的是很便利,但是當組件數量多到一定程度時,結構上就有點可怕,常常在某 GameObject 上掛了組件後就忘了它的存在,雖然可以使用 Singleton design pattern 來製作主要的 Manager(本人對 Singleton 並不是很熱愛),程式還是會亂到一定程度,搜尋了一些 Unity with MVC 討論,一部分的人都對實作 MVC 不是很熱絡,也許是 Unity 特有的開發環境導致。 以前開發 Adobe Flex 專案最愛用的 MVC Framework 就是 PureMVC,即使後來有更方便的 MVC Framework 的也擋不住我對它的熱愛。Unity 是沒有所謂的全域 Root Scene,所有場景都是獨立,想要將 AS3 實作邏輯套用在 Unity 上將控制項都在 PureMVC 架構中實作是有點矯情多餘。如何保持 Unity 組件開發模式,導入 PureMVC 鬆綁主要邏輯,就是這次實驗的重點。 不清楚 PureMVC 的朋友們可以到這邊參觀一下: PureMVC 我也會 PureMVC C# Standard Framework on GitHub ViewComponent 與 Mediator 整合是首要工作: 由於 Unity 沒有全域 Root Scene,如果將 new Mediator( viewComponent ) 寫在 PureMVC 架構下,即使透過 GameObject.Find 找那個對應的 GameObject 就轉了九彎十八拐,寫起來一點都不愉快,尤其考慮到場景的轉換,兩個場景中相關 Mediator 的註冊與移除處理,何況對 Unity 組件來說,能不能被打包動態載入是件重要的事。綜合以上問題點,反向思考,改由 GameObject 掛載中介組件,在 OnEnable 與 OnDisable 通知 Facade 去註冊與移除其 Mediator,一來簡化為了實作 Meditaor 掛載 ViewComponent 而對 static class GameObject 的依賴,二來也不會對 Unity 組件開發模式有太大的影響。

[Swift3] weak 與 unowned 關鍵字

雖然在 Swift 中看起來"很像"是不需要煩惱內存管理的問題,不過實際上它還是遵循著自動引用計數 (ARC) 的規則,當一個物件沒有被其他對象引用時會自動被銷毀,如果三魂七魄沒有完全回位的話,就會有個靈體留在現世的空間裡,最經典的範例如下: 閉包(Closure)引用 classClassA { typealias Complete = ()->() var name : String var onComplete : Complete? init(_ name: String){ self.name = name print("Hello I am \(self.name)") onComplete = { print("\(self.name): onComplete!") // --> 閉包引用 self, 計數 + 1 } } deinit { print("deinit: \(self.name)") } } var a : ClassA? = ClassA("A") // --> 引用計數 + 1 a = nil // 2-1 = 1 還剩下 1 所以沒辦法銷毀 ---output------- Hello I am A 由於這邊的 onComplete 宣告為 Optional, 正確的做法要連同 onComplete 一起刪除才可以被回收,若不是 Optional 則會進入無法回收狀態: var b : ClassA? = ClassA("B") b?.onComplete = nil // --> 還好是 Optional 可以設成 nil 計數 - 1 b = nil // 計數 = 0 所以被回收 ---output------- Hello I am B deinit: B 但是做人不需要煩惱太多,這時候就出動 unowned 關鍵字讓物件可以順利被回收: onComplete = { [unowned self] in print...