java 板


LINE

已明瞭重點不在於 service 該怎麼設計,現在只針對一些細節說明(回覆)我的看法。 ※ 引述《Killercat (殺人貓™)》之銘言: : -------不過其實framework creator端是否真的沒做到轉型安全? 我們看一下 : 如果說是要完全的compile-time check safe,那那隻Supress Warning一定要消掉 : 不過仔細看就可以發現,這是完全語法上的問題,而不是轉型的問題... : private static Map<Class<? extends IService>, IService> serviceMap = new : HashMap<Class<? extends IService>, IService>(); : @SuppressWarnings("unchecked") : static public <T extends IService> T getService(Class<T> clazz) { : return (T)serviceMap.get(clazz); : } : 我們把最關鍵轉型的兩行貼上來看一下 : 乍看之下getService是不安全的,因為他強轉了T回去。但是,仔細看我們就會發現, : 經由精巧的generic限制,所以我們的傳回值理論上不該強轉也該能傳回去。 : 1. T被限制住一定是IService(所以傳入錯誤的.class會編譯爆炸) : 2. T被限制住一定試傳入的Class<T> : 在這兩個條件的限制下去拿取service map,其實已經有足夠的明確性以及把握去指向 : 正確的instance,而這個(T)強轉其實只是語法上不得不為 : 我們在寫Generic的時候其實很多時候都會被迫莫名其妙的強轉T : 完全只是因為compiler time沒辦法去得到T之間的關係而已,所以即使在Framework side : 我相信這邊也是符合了型別安全的要求,而非因為SupressWarning所以有疑慮 我不明白第二點的意思。T被限制住一定是傳入的Class<T>,這與從 serviceMap 取出 一個 value 會是 T 的關聯是? compiler 會給 warning 就是因為它沒有辦法確定他所產生的 code 能夠保證 型別上的正確。 getService method 宣稱它會傳回完全相容於參數所指定的型別的物件,而其實作 是從一個 Map 的 value 而來,依照 serviceMap 的 generics 宣告,只能確定 value 定是 IService 相容的物件(當然這裡不考慮使用 casting 亂搞的行為),getService 的實作中 compiler 所產生的 guarding code 是沒有辦法確定它一定能夠傳回相容於 參數所指定的型別,需要你要求 supress warning 並不是莫名其妙的事情。 編譯器沒有在 compile-time 做到型別上的保證,同樣地你也沒有辦法,你會覺得 你有信心還是在於你去 reasoning 你的程式流程,認定這樣子沒錯。如果這個 serviceMap 不是完全由你掌控(比如它從別處而來或是它的 reference 可擴散到 其他地方),你就不會認為這個 SupressWarning 是沒有疑慮的,不是嗎? : : 你的做法的優點在於你把風險集中在一處,你透過讓他人遵守一個 convension, : : 並讓轉型的風險全落在一個(或一組)較有經驗的人手上;缺點是暴露實作的細節( : : 至少以文內的範例來說),client code 要使用一個 service 他必需要知道實作 : : 這個功能的 class 是哪一個。 : 這點其實我不太懂為什麼叫做暴露細節 : 大多數來講Service都有自己獨特的功能,除非像是CRUDService而且僅僅被限制在CRUD : 我們來分兩部分來講,比方說你提到的以及CRUD,這種Service的特徵是 : "我服務的介面完全相同,差別僅在於我處理的Bean(我們稱為Marsheled Bean)" :[略] : 再來看第二種Service : 這些Service只有部分method是每個Service都相同的 : 但是各個Service有自己獨特的不同,那我們的目標就不是"透過interface操作" : 我們必須讓使用者看到service獨有的功能才能做事 : 就有如我blog裡面提到的第一個NameCardService : 只有他有sort跟getDuplicated,其他Service都沒有 : 這算是惡性的expose嗎?我還真的想不到不expose的方法 XD : 如果你說的是我們應該要有一個INameCardService的話,正好,我們現在的設計有 我認為 service(or plugin) 都是可以在 runtime 去抽換的,那麼 client 一定是 以 interface 去操作之,不可能在編譯期去知道 service 確切實作者(class)。 即便不考慮 runtime 抽換 service/plugin,client 要使用到 class name 來取用 service 的做法,不論是在開發上還是架構設計上,已放棄了許多彈性。 service 由 interface 來定義它的功能,每個 service 都是一個獨立的 interface,不會有"多種 service 由一個 interface 定義共通部分,然後特定 service 有的功能就直接將 service 視為特定 class",而是若 service B 比 service A 多一項功能,就應該有一個 interface 是比 service A interface 多 一項功能的 interface 來定義 service B。(多個 service interface 彼此間可以 行成一組階層) : : 如果目標是讓 client 只透過 initerface 使用 service,在取用 service 時又 : : 不需要指名道姓實作 service 的 class,那麼你這樣的設計該怎麼去改良以 : : 符合目標? 我提出這一點的目的是:依你的範例來說它是個很單純的(陽春),可是即便如此你 還是用到兩個 SupressWarning,這 OK,若你能夠驗證你的設計定不會出錯。 可是若考量其他的需求來改良你的設計,當它變得複雜了,你可能會發現利用參數 來 infer return type 的做法,變得不太容易寫,SupressWarning 越來越難避免 且 SupressWarning 會擴散,情況不再是只有你需要 SupressWarning 你確定它是 無害的,也許 service 的實作者都需要用到 SupressWarning,那麼你就要要求 他們也能夠保證他們的 code 的正確性,否則你當初希望 client 可以很簡單地 取用到有正確編譯期型別的目標就失去了。 *利用 argument 來 infer return type 的做法不算罕見,是不多但我認為這是 因為能這樣用的場合很有限,要寫多這樣的設計又不用到 SupressWarning 更是少, 如果要求實作中所用到的 code(library, core classes)的實作也不使用 SupressWarning 則更少。 在很單純的應用中的話,想要 client 在取用 service 可以有正確的編譯期型別, 為什麼不考慮由你來寫個 Services 這樣的 utility class 來給 client 使用。 class Services { IServiceA getServiceA(...); IServiceB getServiceB(...); ... } 由你來提供這些 method 裡的 wrapper code。 或者是設計像 ServiceRegistry 這種東西,有註冊/取得各種 Service 介面的實作品 的 method,實際使用註冊部分的 code 由你來寫,也可以簡單做到你要的效果。 --



※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 1.172.243.180 ※ 編輯: sbrhsieh 來自: 1.172.243.180 (07/21 03:30)







like.gif 您可能會有興趣的文章
icon.png[問題/行為] 貓晚上進房間會不會有憋尿問題
icon.pngRe: [閒聊] 選了錯誤的女孩成為魔法少女 XDDDDDDDDDD
icon.png[正妹] 瑞典 一張
icon.png[心得] EMS高領長版毛衣.墨小樓MC1002
icon.png[分享] 丹龍隔熱紙GE55+33+22
icon.png[問題] 清洗洗衣機
icon.png[尋物] 窗台下的空間
icon.png[閒聊] 双極の女神1 木魔爵
icon.png[售車] 新竹 1997 march 1297cc 白色 四門
icon.png[討論] 能從照片感受到攝影者心情嗎
icon.png[狂賀] 賀賀賀賀 賀!島村卯月!總選舉NO.1
icon.png[難過] 羨慕白皮膚的女生
icon.png閱讀文章
icon.png[黑特]
icon.png[問題] SBK S1安裝於安全帽位置
icon.png[分享] 舊woo100絕版開箱!!
icon.pngRe: [無言] 關於小包衛生紙
icon.png[開箱] E5-2683V3 RX480Strix 快睿C1 簡單測試
icon.png[心得] 蒼の海賊龍 地獄 執行者16PT
icon.png[售車] 1999年Virage iO 1.8EXi
icon.png[心得] 挑戰33 LV10 獅子座pt solo
icon.png[閒聊] 手把手教你不被桶之新手主購教學
icon.png[分享] Civic Type R 量產版官方照無預警流出
icon.png[售車] Golf 4 2.0 銀色 自排
icon.png[出售] Graco提籃汽座(有底座)2000元誠可議
icon.png[問題] 請問補牙材質掉了還能再補嗎?(台中半年內
icon.png[問題] 44th 單曲 生寫竟然都給重複的啊啊!
icon.png[心得] 華南紅卡/icash 核卡
icon.png[問題] 拔牙矯正這樣正常嗎
icon.png[贈送] 老莫高業 初業 102年版
icon.png[情報] 三大行動支付 本季掀戰火
icon.png[寶寶] 博客來Amos水蠟筆5/1特價五折
icon.pngRe: [心得] 新鮮人一些面試分享
icon.png[心得] 蒼の海賊龍 地獄 麒麟25PT
icon.pngRe: [閒聊] (君の名は。雷慎入) 君名二創漫畫翻譯
icon.pngRe: [閒聊] OGN中場影片:失蹤人口局 (英文字幕)
icon.png[問題] 台灣大哥大4G訊號差
icon.png[出售] [全國]全新千尋侘草LED燈, 水草

請輸入看板名稱,例如:Soft_Job站內搜尋

TOP