Re: [J2SE] 談談Service的設計

看板java作者 (殺人貓™)時間12年前 (2013/07/21 16:50), 編輯推噓0(000)
留言0則, 0人參與, 最新討論串9/9 (看更多)
※ 引述《sbrhsieh (十年一夢)》之銘言: : : 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); : : } : 我不明白第二點的意思。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 是沒有疑慮的,不是嗎? 恩...我大概懂你想表達的意思了,基本上你是對的,我著眼的地方跟你有點落差 我著眼在於"我認定這個是個black box(很有信心)",而你是著眼於整個面向 擴散的問題我有考慮到,所以基本上跟註冊有關的code都會被嚴格限制在private 這也是為什麼這個系統當初不會搞一個什麼RegisterService啥的 而是把Map跟register()嚴格的以private禁錮在BaseService的理由之一 這點你也正確地指出來了。 不過既然我們有"這個設計沒有擴散的問題 只是可能會有Scaling的問題"的共識的話 (下文您就是回覆關於Scaling的問題) 這部分我想應該我跟你意見是一致的,只是你覺得這設計會有其他面向的問題 這倒是一個我沒想過的insignt,謝謝你的指教 "getService()回傳值系統只能保證是個IService 我卻是逼他轉成T (即使他是實作於IService),所以會有warning,而我只是很有信心的設計成他是對的" 這應該就是你所想要表達的概念 : : 這點其實我不太懂為什麼叫做暴露細節 : : 大多數來講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 彼此間可以 : 行成一組階層) : 我提出這一點的目的是:依你的範例來說它是個很單純的(陽春),可是即便如此你 : 還是用到兩個 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 由你來寫,也可以簡單做到你要的效果。 這跟設計哲學有關係。 如果我們可以讓使用者單單只要繼承一個class,接下來他就可以完全使用這些功能 這種把使用者當"設計上的傻瓜"的哲學,在我經驗裡面會省下很多維護上的麻煩 (類似於qttr1說的爽到你艱苦到我) 按照你的寫法的話,使用者或者我,必須去手動幫他們添加一個個的service (我稱這種叫做hard-code registry),一定得有一個人做這件事情 而要是我們甚至只要提供一組jar,要人import,然後繼承某個class寫Service就能搞定 我覺得這是這組機制設計的目的 目前來講Service使用者"都"不需要Supress這個Warning 拿出來的class直接就是已經轉好的class 所以在這個scale目前還沒看到你說的問題(也許以後會有?我不敢說那麼肯定XD 但是這也是我要避免的目標 -- 我連使用者轉型都有疑慮了 還放warning出來要他們supress? 不可能) 我想說的是 logdown裡面用來舉例的是個嚴重簡化過的例子 他想表達的僅僅只是一個generic technique,而非一個完整的Service設計概念 是我Service設計概念中的一部分(我在回給您的回覆中有提到我們現行Service是 怎麼跑的,您可以清楚的看到Service因為某些理由,是有自己的獨立Interface 比方說我回覆給您的IMasterChannelService) 目前設計上是可以把IService/BaseService包成jar給使用者去跑,把這端一刀切成 Framework端,而使用者要做的是引入這個jar 繼承BaseService 然後寫自己的ISomeService 不過我想現在我不管怎麼講,應該都不夠清楚 =P 因為其實這篇該說的應該僅僅只是Generic Technique 關於Service的設計上,除了您給的demo code我沒辦法贊同以外 其實應該在大多數的想法上我跟你都是in the same page 不過您提到的SupressWarning方面的看法面向也是很重要,感謝指教 相信等我有空把真正的Service設計哲學提出大家分享的時候 應該會激起更多的水花 :) 另外有一點我比較困擾的是,很多code其實是以C++ policy based design寫出來的 要怎麼把他轉成java跟大家一起討論架構設計 其實對我已經是個很嚴苛的挑戰了(汗) -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 119.14.20.94 ※ 編輯: Killercat 來自: 119.14.20.94 (07/21 16:53)
文章代碼(AID): #1Hww3Kiw (java)
討論串 (同標題文章)
文章代碼(AID): #1Hww3Kiw (java)