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灯, 水草

请输入看板名称,例如:e-shopping站内搜寻

TOP