作者Killercat (杀人猫™)
看板java
标题Re: [J2SE] 谈谈Service的设计
时间Sun Jul 21 16:50:26 2013
※ 引述《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)